如何将ts节点ESM与节点模块一起使用



注意:我知道下面的问题是关于一个实验特性的。我在ts节点讨论论坛上创建了一个克隆。然而,我相信StackOverflow有更广泛的风险敞口,并将在更短的时间内找到解决方案。

我正在尝试制作一个简单的脚本,从一个位置读取文件并对其进行处理

节点:v12.22.1

my-app
├── .eslintrc.cjs
├── .gitignore
├── in
│   └── given.txt
├── node_modules
├── out
├── package-lock.json
├── package.json
├── src
│   ├── helper.ts
│   └── main.ts
└── tsconfig.json

软件包.json

{
"name": "my-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings=0",
"start": "node --experimental-specifier-resolution=node --experimental-modules --no-warnings --loader ts-node/esm ./src/main.ts"
},
"author": "Kaustubh Badrike",
"devDependencies": {
"@types/node": "^15.3.0",
"@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0",
"eslint": "^7.26.0",
"ts-node": "^9.1.1",
"typescript": "^4.2.4"
}
}

tsconfig.json

{
"compilerOptions": {
"target": "es5",                                /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "ESNext",                           /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */

/* Strict Type-Checking Options */
"strict": true,                                 /* Enable all strict type-checking options. */

/* Module Resolution Options */
"moduleResolution": "node",                  /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"esModuleInterop": true,                        /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

/* Advanced Options */
"skipLibCheck": true,                           /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true        /* Disallow inconsistently-cased references to the same file. */
}
}

主.ts

import { readFileSync } from "fs";
const contents = readFileSync('../in/given.txt');

然而,当我尝试npm run start时,我会得到以下

TypeError [ERR_INVALID_RETURN_PROPERTY_VALUE]: Expected string to be returned for the "format" from the "loader getFormat" function but got type 
object.
at Loader.getFormat (internal/modules/esm/loader.js:125:13)
at Loader.getModuleJob (internal/modules/esm/loader.js:247:20)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:49:17)
at async Promise.all (index 0)
at link (internal/modules/esm/module_job.js:53:9)

如果我从fs中删除导入,则不会发生错误。从helper.ts导入项目也可以。

我需要做什么才能让它工作

来自此问题的评论:

在Node 16中,调用TypeScript代码时可以使用ts-node-esm

总之,在tsconfig.json文件中,设置

"module": "ESNext",
"moduleResolution": "node"

package.json中设置

"type": "module"

然后,在运行脚本时,不要运行ts-node myscript.ts,而是通过ts-node-esm myscript.ts调用它

更新时间:2021年5月23日

ts节点v10.0.0已经发布,它修复了NodeJS上ESM加载程序中节点内置模块的解析>12.20.0,<13这似乎是你面临的问题。

原始答案

我可以在NodeJS 12.22.1上重现您的问题。我也可以确认它在NodeJS 14.16中正常工作。

有可能更新你的NodeJS版本吗?

请记住,NodeJS对ESM的支持在很长一段时间内都是实验性的,在这个阶段通常会发生变化。

此外,鉴于您使用的NodeJS(12.X(版本的维护寿命即将结束,我建议您将NodeJS至少更新到14.X版本,以解决此问题,并从最新开发中受益,并保证长期支持。

您可以在这里找到关于需求和配置的更完整的答案:无法在节点中导入ESM.ts模块

最新更新