简体   繁体   English

TypeScript 与 Node.js ESM 不一致

[英]TypeScript with Node.js ESM disagreement

Node.js ESM seems work differently than TypeScript. Node.js ESM 的工作方式似乎与 TypeScript 不同。

It's resulting in programs that pass typechecking and yet crash at runtime.它导致程序通过类型检查但在运行时崩溃。

package.json package.json

{
  "dependencies": {
    "@types/lodash": "^4.0.0",
    "lodash": "^4.0.0",
    "typescript": "^4.0.0"
  },
  "type": "module"
}

tsconfig.json tsconfig.json

{
  "compilerOptions": {
    "module": "es2015"
  }
}

a.ts a.ts

import { partition } from "lodash";

partition([1, 2, 3, 4], n => n % 2);

Run

npm install
node_modules/.bin/tsc -p .
node index.js

And the program crashes:程序崩溃:

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)

How can I bring TypeScript and Node.js ESM into alignment, so that typechecking matches runtime behavior?如何将 TypeScript 和 Node.js ESM 带入 alignment,以便类型检查与运行时行为相匹配?


EDIT:编辑:

I have tried using typescript@next with "module": "nodenext" .我尝试将 typescript@next 与"module": "nodenext"使用。

The same error happens.发生同样的错误。

The problem is that you're mixing ES and ComonJS modules;问题是你混合了 ES 和 ComonJS 模块; it's in the text of the error message.它在错误消息的文本中。 This is still a relatively new concept and is easy to miss when you'd expect that modules... should... just work.这仍然是一个相对较新的概念,当您期望模块......应该......正常工作时很容易错过。

TypeScript only provides import statements, which they will then transpile to your chosen module system; TypeScript 仅提供import语句,然后它们将转译到您选择的模块系统; in the case of ESM, there's not a whole lot to transpile as they're syntactically similar.在 ESM 的情况下,由于它们在语法上相似,所以没有太多需要转换的地方。

Since you're transpiling to ESM, the problem is not TypeScript;由于您要转译为 ESM,因此问题不在于 TypeScript; it's the underlying Node.js engine and how it deals with mixed module systems.它是底层 Node.js 引擎以及它如何处理混合模块系统。 You've written something in ESM (granted, using TypeScript) and you're trying to import something else written in CommonJS.您已经在 ESM 中编写了一些内容(授予,使用 TypeScript)并且您正在尝试导入用 CommonJS 编写的其他内容。

In order to execute your code depending on a CommonJS module, you either need to:为了根据 CommonJS 模块执行代码,您需要:

  1. Use the ESM version of your dependency (and not all dependencies provide one!)使用您的依赖项的 ESM 版本(并非所有依赖项都提供一个!)
  2. Use module.createRequire() to import the CommonJS module in a usable form使用module.createRequire()以可用的形式导入 CommonJS 模块

Sources:资料来源:

https://nodejs.org/api/esm.html#no-require-exports-or-moduleexports https://nodejs.org/api/module.html#modulecreaterequirefilename https://nodejs.org/api/esm.html#no-require-exports-or-moduleexports https://nodejs.org/api/module.html#modulecreaterequirefilename

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM