Typescript ESM tsconfig - 从 tsconfig 内部读取的 属性(ies)/values 确定输出是否为 ESM?

Typescript ESM tsconfig - which property(ies)/values read internally from tsconfig definitely tell if output is ESM?

我正在编写一个打字稿 API 转换,它在发出阶段处理源文件。我可以通过 program.getCompilerOptions().

访问 compileOptions 的内部值的转换

我需要知道输出是 'CommonJS'、esm 脚本还是其他。 我想我可以从 module 字段看出,但我不确定。 打字稿定义 -

  //   export enum ModuleKind {
  //     None = 0,
  //     CommonJS = 1,
  //     AMD = 2,
  //     UMD = 3,
  //     System = 4,
  //     ES2015 = 5,
  //     ES2020 = 6,
  //     ...
  //     ESNext = 99
  // }

而且我想我可以使用这个逻辑 -

  const moduleKind: ts.ModuleKind | undefined =
    program.getCompilerOptions().module;
  if (!moduleKind) {
    throw new Error(
      `compilerOptions.module is undefined (should have default value)`
    );
  }
  if (
    moduleKind < ts.ModuleKind.ES2015 &&
    moduleKind !== ts.ModuleKind.CommonJS
  ) {
    // not esm and not commonjs
  }
  else if (moduleKind === ts.ModuleKind.CommonJS) {
    // commonjs
  } else {
    // esm
  }

然而,在打字稿上 tsconfig man page for the module property 它在边栏中列出了这些 allowed values

none
commonjs
amd
umd
system
es6/es2015
es2020
es2022
esnext
node12
nodenext 

从中 node12nodenext 几乎可以肯定是“commonjs”。 这让我觉得也许某些值 >=es6/es2015 可能是(如果不是今天,那么有一天)非 esm 值。我正在寻找这个问题的明确答案, 因为手册没有明确回答这个问题。

我在打字稿问题上开了一个问题 Clarity on how to determine progmatically whether a sourceFile is to be output as "commonjs" or "esm". #48794 并获得了解决方案。

来自 Typescript 代码文档

(property) SourceFile.impliedNodeFormat?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined

When module is Node12 or NodeNext, this field controls whether the source file in question is an ESNext-output-format file, or a CommonJS-output-format module. This is derived by the module resolver as it looks up the file, since it is derived from either the file extension of the module, or the containing package.json context, and affects both checking and emit.

It is public so that (pre)transformers can set this field, since it switches the builtin node module transform. Generally speaking, if unset, the field is treated as though it is ModuleKind.CommonJS.

一个 API 客户端试图确定 per-Program、per-SourceFile 是否会被转换为 definitely-CommonJs、definitely-Esm 或其他,可以使用此编码逻辑:

if SourceFile.impliedNodeFormat===ModuleKind.CommonJS, then "commonjs"
else if SourceFile.impliedNodeFormat===ModuleKind.ESNext, then "module"
else if compilerOptions.module===ts.ModuleKind.CommonJS, then "commonjs"
else if compilerOptions.module>=ts.ModuleKind.ES2015, then "module"
else not definitely "commonjs" nor definitely "module"