TypeScript 与 Node.js ESM 分歧
TypeScript with Node.js ESM disagreement
Node.js ESM 的工作方式似乎与 TypeScript 不同。
这导致程序通过了类型检查,但在运行时却崩溃了。
package.json
{
"dependencies": {
"@types/lodash": "^4.0.0",
"lodash": "^4.0.0",
"typescript": "^4.0.0"
},
"type": "module"
}
tsconfig.json
{
"compilerOptions": {
"module": "es2015"
}
}
a.ts
import { partition } from "lodash";
partition([1, 2, 3, 4], n => n % 2);
运行
npm install
node_modules/.bin/tsc -p .
node index.js
程序崩溃:
file:///home/paul/test44/index.js:1
import { partition } from "lodash";
^^^^^^^^^
SyntaxError: Named export 'partition' not found. The requested module 'lodash' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'lodash';
const { partition } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:179:5)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5)
at async handleMainPromise (node:internal/modules/run_main:63:12)
如何使 TypeScript 和 Node.js ESM 对齐,以便类型检查匹配运行时行为?
编辑:
我试过将 typescript@next 与 "module": "nodenext"
一起使用。
发生同样的错误。
问题是您混合了 ES 和 ComonJS 模块;它在错误消息的文本中。这仍然是一个相对较新的概念,当您期望模块……应该……正常工作时,很容易错过。
TypeScript 仅提供 import
语句,然后它们将转换为您选择的模块系统;在 ESM 的情况下,没有很多东西可以转译,因为它们在语法上很相似。
由于您正在转换为 ESM,问题不在于 TypeScript;它是底层 Node.js 引擎以及它如何处理混合模块系统。您已经用 ESM 编写了一些东西(当然,使用 TypeScript)并且您正在尝试导入用 CommonJS 编写的其他东西。
为了根据 CommonJS 模块执行代码,您需要:
- 使用依赖项的 ESM 版本(并非所有依赖项都提供一个!)
- 使用
module.createRequire()
以可用形式导入CommonJS模块
来源:
https://nodejs.org/api/esm.html#no-require-exports-or-moduleexports
https://nodejs.org/api/module.html#modulecreaterequirefilename
Node.js ESM 的工作方式似乎与 TypeScript 不同。
这导致程序通过了类型检查,但在运行时却崩溃了。
package.json
{
"dependencies": {
"@types/lodash": "^4.0.0",
"lodash": "^4.0.0",
"typescript": "^4.0.0"
},
"type": "module"
}
tsconfig.json
{
"compilerOptions": {
"module": "es2015"
}
}
a.ts
import { partition } from "lodash";
partition([1, 2, 3, 4], n => n % 2);
运行
npm install
node_modules/.bin/tsc -p .
node index.js
程序崩溃:
file:///home/paul/test44/index.js:1
import { partition } from "lodash";
^^^^^^^^^
SyntaxError: Named export 'partition' not found. The requested module 'lodash' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'lodash';
const { partition } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:179:5)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5)
at async handleMainPromise (node:internal/modules/run_main:63:12)
如何使 TypeScript 和 Node.js ESM 对齐,以便类型检查匹配运行时行为?
编辑:
我试过将 typescript@next 与 "module": "nodenext"
一起使用。
发生同样的错误。
问题是您混合了 ES 和 ComonJS 模块;它在错误消息的文本中。这仍然是一个相对较新的概念,当您期望模块……应该……正常工作时,很容易错过。
TypeScript 仅提供 import
语句,然后它们将转换为您选择的模块系统;在 ESM 的情况下,没有很多东西可以转译,因为它们在语法上很相似。
由于您正在转换为 ESM,问题不在于 TypeScript;它是底层 Node.js 引擎以及它如何处理混合模块系统。您已经用 ESM 编写了一些东西(当然,使用 TypeScript)并且您正在尝试导入用 CommonJS 编写的其他东西。
为了根据 CommonJS 模块执行代码,您需要:
- 使用依赖项的 ESM 版本(并非所有依赖项都提供一个!)
- 使用
module.createRequire()
以可用形式导入CommonJS模块
来源:
https://nodejs.org/api/esm.html#no-require-exports-or-moduleexports https://nodejs.org/api/module.html#modulecreaterequirefilename