什么 TypeScript 配置产生最接近 Node.js 14 功能的输出?

Lin*_*äck 46 node.js typescript

随着 Node.js 更新了对 ES2020 的支持并添加了对 ES 模块的支持,如何配置 TypeScript 以输出利用所有这些新功能的 JavaScript 代码?

Lin*_*äck 150

从 Node.js 开始14.0.0,100% 支持 ES2020,并且对 ES Modules 的支持已经落地!如果您知道您的目标是该版本或更新版本,则最佳配置如下所示:

  • "module": "ES2020" & "moduleResolution": "node"

    Node.js 14 支持加载模块而不是旧的 CommonJS 格式,我们必须告诉 TypeScript 我们正在使用 Node.js 的规则来解析模块。

  • "allowSyntheticDefaultImports": true

    为了提供向后兼容性,Node.js 允许您使用默认导入来导入 CommonJS 包。这个标志告诉 TypeScript 可以import在 CommonJS 模块上使用。

  • "target": "ES2020"

    这告诉 TypeScript 可以输出带有 ES2020 特性的JavaScript语法。在实践中,这意味着它将输出可选的链接操作符和 async/await 语法,而不是嵌入一个 polyfill。

  • "lib": ["ES2020"]

    这告诉 TypeScript 可以使用ES2020 或更早版本中引入的函数和属性。实际上,这意味着您可以使用 egPromise.allSettledBigInt

因此,完整的配置将是:

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "lib": ["ES2020"],
    "module": "ES2020",
    "moduleResolution": "node",
    "target": "ES2020"
  }
}
Run Code Online (Sandbox Code Playgroud)

除此之外,我们还需要告诉 Node.js 将.js这个项目中的文件视为 ES Modules。这样做的原因是 Node.js 必须保持与为旧 Node.js 版本编写的代码的向后兼容性。这可以通过添加"type": "module"到您的package.json

{
  "type": "module"
}
Run Code Online (Sandbox Code Playgroud)

如果您来自早期版本的 Node.js,另一个变化是导入文件时的文件扩展名现在是必需的。这意味着您必须.js在本地导入的末尾写出。请注意,.js即使您正在导入实际具有文件扩展名的 TypeScript 文件,也是如此.ts。这似乎有点令人困惑,但来自一位 TS 贡献者的评论解释了为什么会这样

以下是一些如何编写import语句的示例:

// Built-in Node.js modules
import { readFileSync } from 'fs'

// CommonJS packages from Npm
import md5File from 'md5-file'

// The local file "a.ts"
import { a } from './a.js'
Run Code Online (Sandbox Code Playgroud)

如果你现在想坚持使用 CommonJS,为了避免上面解释的警告,你可以使用以下配置:

{
  "compilerOptions": {
    "lib": ["ES2020"],
    "module": "CommonJS",
    "target": "ES2020"
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在运行 Node.js 16,您可以在此处看到我对 Node.js 16 的类似回答

如果您正在运行 Node.js 12,您可以在此处看到我对 Node.js 12 的类似回答

如果您正在运行 Node.js 10,您可以在此处看到我对 Node.js 10 的类似回答

如果你正在运行 Node.js 8 你可以在这里看到我对 Node.js 8 的类似回答

  • 这正是我一直在寻找的,感谢您领先于 [Microsoft](https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping)。 (4认同)
  • 有一种方法可以在导入时省略 .js 扩展名,我在我的 [modern-typescript-project](https://github.com/dandv/typescript-modern-project#import-your-own-模块(不指定扩展名)存储库。除此之外,感谢您挑战使用 TypeScript 生成 ES 模块代码的极限!我们希望 TypeScript 模块作者开始采用这一点并[发布适当的 ES 模块](https://github.com/typegoose/typegoose/issues/214)。 (3认同)
  • “esModuleInterop”怎么样?我推断它可以或必须为假,因为您明确设置了“allowSyntheticDefaultImports”。 (2认同)