TypeScript [transform API]:允许将getEmitResolver传递到TransformationContext中,并从Program中公开getEmitResolver,

hpcdzsge  于 4个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(55)

建议

🔍 搜索词

  • getEmitResolver
  • transform API

✅ 可实现性检查清单

我的建议符合以下指导原则:

  • 这不会对现有的TypeScript/JavaScript代码造成破坏性的更改
  • 这不会改变现有JavaScript代码的运行时行为
  • 这可以在不根据表达式的类型发射不同的JS的情况下实现
  • 这不是一个运行时特性(例如库功能、使用JavaScript输出的非ECMAScript语法、JS的新语法糖等)
  • 这个特性将与 TypeScript's Design Goals 的其他部分一致。

⭐ 建议

transform API非常方便,因为使用这个API不需要调用Program来将ts编译为js以使用自定义AST转换器。然而,它不允许需要访问EmitResolver的情况。如果transform API可以让用户将getEmitResolver传递到TransformationContext中,那就太好了。
目前,getEmitResolver既没有暴露给TransformationContext接口,也没有暴露给Program接口。

📃 激励示例

一个理想的示例应该是这样的

export function constructorParametersDownlevelTransform(program: ts.Program): ts.TransformerFactory<ts.SourceFile> {
  const typeChecker = program.getTypeChecker();
  const reflectionHost = new TypeScriptReflectionHost(typeChecker);

  return (ctx: ts.TransformationContext) => {
    return getDownlevelDecoratorsTransform(
      typeChecker,
      reflectionHost,
      [],
      false,
      false,
      true,
    )({
      ...ctx,
      getEmitResolver: ctx.getEmitResolver()
        ? ctx.getEmitResolver
        : program.getDiagnosticsProducingTypeChecker().getEmitResolver,
    });
  };
}

💻 用例

我正在尝试实验这个想法:

  • 使用transform API处理TypeScript源代码的AST,并使用一些自定义AST转换器。
  • 使用swcesbuild将经过新转换的源代码编译为ts

据我所知,使用transform API处理AST相当快。如果我可以在不使用Program进行完整的编译步骤的情况下处理AST,而是使用swcesbuild进行编译,那么这将有助于我实现目标:快速编译+源代码以我想要的方式进行处理(Jest提升、Angular下级构造函数等...)

7kqas0il

7kqas0il1#

@rbuckton,你有什么想法?

toe95027

toe950272#

在谷歌,我们也会从将 EmitResolver 应用于转换器中受益。用例:
为了在开发过程中提高编辑/刷新性能,我们希望将 TS 转译为 JS,而不进行类型检查。理想情况下,我们会使用 ts.transpileModule() 来实现这一点。然而,我们仍然需要进行一些转换,对于两种情况,我们看不到不使用类型检查器或发出解析器就能实现它们的方式:

  • 要转换用户编写的 .default 访问导入,我们需要找到给定标识符的导入声明(代码)。EmitResolver#getReferencedImportDeclaration 在这里会有所帮助。
  • 要转换导入并仍然省略仅包含类型的导入,我们需要知道给定标识符是否在值位置中使用。EmitResolver#isReferencedAliasDeclaration 在这里会有所帮助。

@rbuckton,你是否考虑将 EmitResolver 及其一些方法设为公共?

jq6vz3qz

jq6vz3qz3#

暴露程序的 EmitResolver 也会使诸如 dts-bundle-generator@microsoft/api-extractor 等工具受益 - 在这种情况下,我们需要在生成新节点或更新现有节点时执行名称冲突解决,并尽可能保留用户的输入。如果不暴露任一程序的 EmitResolverglobalThis 符号,将会出现相当大的问题甚至不可能。
仅供参考,@microsoft/api-extractor 已经在使用内部方法来获取 EmitResolver 以使用 hasGlobalName 执行描述的检查。
@andrewbranch@rbuckton 你是否对将其公开有任何顾虑?

cigdeys3

cigdeys34#

EmitResolver 主要是针对 TypeChecker 的一个关注发射的 Package 器。你几乎总是可以直接从检查器获取相同的信息,如果你正在使用我们的 API 运行自定义转换器,你已经可以访问检查器了。我更感兴趣的是,是否存在我们应该在 TypeChecker 上公开的缺失功能。例如,与其仅仅为了访问 hasGlobalName 而使 EmitResolver 公开,我们可以相反地公开 TypeChecker 现有的 resolveName 方法以实现相同的功能,即:checker.resolveName(name, /*location*/ undefined, SymbolFlags.All, /*excludeGlobals*/ false)

flvlnr44

flvlnr445#

我们可以为相同的功能暴露TypeChecker现有的resolveName方法,即:checker.resolveName(name, /location/ undefined, SymbolFlags.All, /excludeGlobals/ false)。
@rbuckton 这个想法很有道理,谢谢!对于这个特定的用例,我可以创建一个打开此API的PR吗?

相关问题