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

Kau*_*ike 18 node.js typescript ts-node

注意:我知道以下问题是关于实验性功能的。我在 ts-node 讨论论坛上创建了一个克隆。不过,我相信 StackOverflow 拥有更广泛的曝光度,并且会在更短的时间内找到解决方案。

\n

我正在尝试制作一个简单的脚本,从一个位置读取文件并处理它。这是我到目前为止所得到的,遵循#1007

\n

节点:v12.22.1

\n
my-app\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .eslintrc.cjs\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .gitignore\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 in\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 given.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 node_modules\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 out\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package-lock.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 helper.ts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.ts\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n
Run Code Online (Sandbox Code Playgroud)\n

包.json

\n
my-app\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .eslintrc.cjs\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .gitignore\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 in\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 given.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 node_modules\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 out\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package-lock.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 helper.ts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.ts\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig.json

\n
{\n  "compilerOptions": {\n    "target": "es5",                                /* Specify ECMAScript target version: \'ES3\' (default), \'ES5\', \'ES2015\', \'ES2016\', \'ES2017\', \'ES2018\', \'ES2019\', \'ES2020\', or \'ESNEXT\'. */\n    "module": "ESNext",                           /* Specify module code generation: \'none\', \'commonjs\', \'amd\', \'system\', \'umd\', \'es2015\', \'es2020\', or \'ESNext\'. */\n    \n    /* Strict Type-Checking Options */\n    "strict": true,                                 /* Enable all strict type-checking options. */\n    \n    /* Module Resolution Options */\n    "moduleResolution": "node",                  /* Specify module resolution strategy: \'node\' (Node.js) or \'classic\' (TypeScript pre-1.6). */\n    "esModuleInterop": true,                        /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies \'allowSyntheticDefaultImports\'. */\n    \n    /* Advanced Options */\n    "skipLibCheck": true,                           /* Skip type checking of declaration files. */\n    "forceConsistentCasingInFileNames": true        /* Disallow inconsistently-cased references to the same file. */\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

主要.ts

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

但是,当我尝试时npm run start,我得到以下结果

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

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

\n

我需要做什么才能让它发挥作用?

\n

mat*_*ich 11

来自本期评论

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

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

"module": "ESNext",
"moduleResolution": "node"
Run Code Online (Sandbox Code Playgroud)

package.json集合中

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

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


Fel*_*ets 3

更新2021年5月23日

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

原答案

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

可以更新你的 NodeJS 版本吗?

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

另外,与您使用的 NodeJS (12.X) 版本接近其维护寿命这一事实相关,我的建议是您将 NodeJS 更新到至少版本 14.x 要么解决此问题,要么您可以从最新的发展中受益并保证长期支持。

您可以在此处找到有关要求和配置的更完整答案:Unable to import ESM .ts module in node