运行 Typescript 编译器插件/转换器后进行类型检查

Wer*_*oot 3 plugins transformer-model typescript

我正在关注有关如何编写 Typescript 编译器插件/转换器的博客(https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943)。

在应用应该引入类型错误的第一个简单转换(在没有该属性的对象上访问的某些属性)之后,我注意到没有显示类型错误。事实上,编译器照常进行。

import * as ts from "typescript";

export const transformerFactory = (
  program: ts.Program
): ts.TransformerFactory<ts.SourceFile> => {
  return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
    const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
      if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
        if (node.expression.escapedText === "someCall") {
          return ts.createCall(
            ts.createPropertyAccess(node.expression, "nonExisting"),
            node.typeArguments,
            node.arguments
          );
        }
      }
      return ts.visitEachChild(node, visitor, context);
    };

    return (sf: ts.SourceFile) => ts.visitNode(sf, visitor);
  };
};
Run Code Online (Sandbox Code Playgroud)

适用于index.ts

declare function someCall(...args: any[]): string;

console.log(someCall(1, 2, true));
Run Code Online (Sandbox Code Playgroud)

产量index.js

console.log(someCall.nonExisting(1, 2, true));
Run Code Online (Sandbox Code Playgroud)

(即使有noEmitOnError: true

这是预期的行为吗?这是我可以在某处启用的东西吗?

art*_*tem 5

这是预期的行为吗?

是的。

这是我可以在某处启用的东西吗?

不,变压器的用途有限。不支持编译器的通用通用“插件”。

Transformer 作为“emit”阶段的一部分运行,该阶段从类型检查的 AST 生成 javascript 代码。

变压器公关中的这条评论

所有的转换都发生在检查阶段之后

更新

有什么方法可以编译两次:一次转换文件,一次对整个内容进行类型检查?我不介意是否必须对转换后的文件进行单独检查。

我不知道。首先要尝试让您的转换器像以前一样修改 AST,然后通过调用手动键入检查修改后的文件

program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)
Run Code Online (Sandbox Code Playgroud)

(getDiagnostics有第二个参数 - cancellationToken- 但省略它似乎是安全的,因为它总是undefined在类型检查器代码中进行检查。通常,您可以查看各种编译器 API 在其自己的源代码中的使用方式,例如emittype-首先通过调用各种检查program.getNNNDiagnostics,然后运行带有变换的发射器。)

这可能会也可能不会起作用,因为类型检查器会修改 AST,并且这取决于 AST 处于正确的状态。

然后,您可能需要查看构建器 API - 它的目的是监视源文件修改并重新编译更改的文件(源代码链接)。我不知道在 AST 修改时重新编译它会有多困难,而且看起来您将无法使用变压器中可用的访问者;您必须手动遍历 AST。

此外,还有ts-simple-ast库,其声明的目的是“提供一种简单的方法来导航和操作 TypeScript 和 JavaScript 代码”。我自己没有使用过它,也不知道它对你的目标有多大用处。