首页 > 解决方案 > 运行 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);
  };
};

适用于index.ts

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

console.log(someCall(1, 2, true));

产量index.js

console.log(someCall.nonExisting(1, 2, true));

(即使有noEmitOnError: true

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

标签: typescriptpluginstransformer

解决方案


这是预期的行为吗?

是的。

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

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

Transformers 作为“发射”阶段的一部分运行,该阶段从经过类型检查的 AST 生成 javascript 代码。

变形金刚公关中的这条评论说

转换,所有这些都发生在检查阶段发生之后

更新

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

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

program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)

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

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

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

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


推荐阅读