gpt4 book ai didi

typescript - 在类型检查之前转换 typescript

转载 作者:行者123 更新时间:2023-12-04 08:53:57 36 4
gpt4 key购买 nike

让我们以 typescript 文件为例:

class A {
private x? = 0;
private y? = 0;

f() {
console.log(this.x, this.y);
delete this.x;
}
}

const a = new A();
a.f();
我正在使用 awesome-typescript-loader 在 webpack 中构建它:
{
test: /\.tsx?$/,
include: path.resolve("./src"),
exclude: path.resolve("./node_modules/"),
use: {
loader: 'awesome-typescript-loader',
options: {
getCustomTransformers: program => ({
before: [deleteTransformer(program)]
})
}
}
},
哪里 deleteTransformer是我自己的变压器,可以代替任何 delete表达者 delete this.y :
import * as ts from "typescript";

export default function getCustomTransformers(program: ts.Program): ts.TransformerFactory<ts.SourceFile> {
return (context: ts.TransformationContext) => (file: ts.SourceFile) => visitNodeAndChildren(file, program, context);
}

function visitNodeAndChildren<N extends ts.Node>(node: N, program: ts.Program, context: ts.TransformationContext): N {
return ts.visitEachChild(visitNode(node, program), childNode => visitNodeAndChildren(childNode, program, context), context);
}

function visitNode<N extends ts.Node>(node: N, program: ts.Program): N {
if (ts.isDeleteExpression(node)) {
return ts.factory.createDeleteExpression(ts.factory.createPropertyAccessExpression(
ts.factory.createThis(),
"y",
)) as ts.Node as N;
}

return node;
}
如果我运行编译,我会得到我期望的代码(删除 y ,而不是 x ):
/***/ "/7QA":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var A = /** @class */ (function () {
function A() {
this.x = 0;
this.y = 0;
}
A.prototype.f = function () {
console.log(this.x, this.y);
delete this.y;
};
return A;
}());
var a = new A();
a.f();


/***/ }),
但是如果我更改名称 yz不存在于类 A我不会收到任何错误消息。
另外如果我换类 A有非可选 x并保留 y在变压器中,我会得到一个错误
× 「atl」: Checking finished with 1 errors

ERROR in [at-loader] ./src/index.ts:7:16
TS2790: The operand of a 'delete' operator must be optional.
根据这些事实我明白 实际检查代码后应用transformer ,但变压器包含在 before 中部分,所以我希望 typescript 验证生成的代码而不是原始代码。
为什么会发生? before有什么区别和 after变压器 getCustomTransformers对象(我都试过了,没有发现区别)?以及如何应用转换 之前 代码被检查?

最佳答案

在较高级别上,TypeScript 编译器旨在按以下顺序执行以下步骤:

Parse -> Bind -> Type Check -> Emit (transform)
由于这种设计,类型检查器代码通常假定解析时创建的 AST 与源文件文本匹配并且没有改变。
例如:
// `declaration` is a variable declaration with type `number`
console.log(typeChecker.typeToString(
typeChecker.getTypeAtLocation(declaration) // number
));

declaration = factory.updateVariableDeclaration(
declaration,
declaration.name,
/* exclamation token */ undefined,
/* type */ factory.createTypeReferenceNode("Date", undefined),
/* initializer */ undefined,
);

// now type checking won't be reliable
console.log(typeChecker.typeToString(
typeChecker.getTypeAtLocation(declaration) // still number
));
console.log(typeChecker.typeToString(
typeChecker.getTypeAtLocation(declaration.type!) // any
));
因此,您不能可靠地仅转换 AST,然后使用现有的 TypeScript Compiler API 代码进行类型检查。这就是为什么 ts-morph的原因之一实际上是对文本而不是 AST 进行修改,然后重建 AST。需要更新源文件文本和许多内部属性才能正确执行此操作。也就是说,在某些情况下,您可能能够逃脱惩罚……
我不确定 TS 团队在类型检查之前更新编译器以处理转换需要付出什么样的努力,我不确定他们是否会投入精力,但您可能想与他们交谈并问这个。见 checker.ts所有导致 getTextOfNodeFromSourceText 的电话对于一堆这将是一个问题的情况。
before之间的区别和 aftergetCustomTransformers
正如您所注意到的,这两种变换都在发射时使用,而不是在发射之前使用。
  • before - 在编译器进行转换之前要评估的转换——它仍然会在 AST 中包含 TypeScript 代码。
  • after - 在编译器进行转换后要评估的转换——它将被转换为任何“目标”(例如,打印 AST 将给出 JavaScript 代码)。

  • the type declarations更多细节。

    关于typescript - 在类型检查之前转换 typescript ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63947663/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com