首页 > 解决方案 > 如何使用 NodeJS 13 和 Typescript 3.8 导入 esm 模块?

问题描述

我在 NodeJS 中的一些导入有问题。我想使用 Typescript 3.8 的新功能,比如私有字段:#myPrivateField

我不知道如何在课堂上正确导入模块“typescript”。我尝试了很多选择,但无法解决我的问题。

我的文件 :

包.json

{
  "name": "test",
  "scripts": {
    "start": "tsc && node --experimental-modules --es-module-specifier-resolution=node main.js"
  },
  "dependencies": {
    "@types/node": "^13.13.2",
    "app-root-path": "^3.0.0",
    "fs-extra": "^9.0.0",
    "tsutils": "^3.17.1"
  },
  "devDependencies": {
    "ts-node": "~8.3.0",
    "typescript": "^3.8.3"
  },
  "type": "module"
}

tsconfig.json

{
  "compilerOptions": {
    "lib": [
      "ESNext",
      "es2016",
      "dom",
      "es5"
    ],
    "module": "esnext",
    "moduleResolution": "Node",
    "sourceMap": true,
    "target": "es6",
    "typeRoots": [
      "node_modules/@types"
    ]
  }
}

main.ts

// import ts = require("typescript");
import * as ts from "typescript";

export class Main {

    node: ts.Node;
    #test = 'zzz';

    constructor() {}

    process(): void {
        ts.forEachChild(this.node, function cb() {
        });
        console.log('#test', this.#test);
    }
}

const main = new Main();
main.process();

使用此代码,当我运行时npm run start,出现错误TypeError: ts.forEachChild is not a function

如果没有它的行,ts.forEachClid()则正确记录私有字段#test 的值。

如果我尝试替换import * as ts from "typescript";import ts = require("typescript");,我有错误TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead

当然,我在 tsconfig.json 和 package.json 中尝试了很多更改(使用 `"type" = "module"),但无法解决这个问题。

我什至尝试用 替换"module": "esnext""module": "commonjs"但我有一个错误exports is not defined

备注:这不是特定于模块“打字稿”。我对“fs-extra”等其他模块也有同样的问题,这些模块以与大多数经典 NodeJS 模块不同的方式进行导出。

例如,模块“typescript”导出为export = ts.

我也找到了这个参考,但它对我没有多大帮助: https ://www.typescriptlang.org/docs/handbook/modules.html

我的 nodeJs 版本是 13.3.0,我的 typescript 版本是 3.8.3 感谢您的帮助

标签: node.jstypescriptimportmodule

解决方案


ESM 模块仍处于实验模式,有很多模块不支持它,例如使用module.exports(CommonJS)而不是export(ESM)。

您最好的选择是使用commonjs模块并在node没有任何标志的情况下运行。此外,type包装中的package.json必须也是commonjs如此。


回答您的问题“如何导入 ESM 模块”... 如果模块确实支持ESM 模块,您可以import像往常一样使用:

import { something } from './something';

UPD:正如 OP 作者所提到的,要使私有字段起作用,必须设置一个 target es2018。这背后的原因是私有字段不是 ES2015 规范的一部分,您需要升级到最小​​支持目标才能做到这一点。

"compilerOptions": {
  "module": "commonjs",
  "moduleResolution": "node",
  "target": "es2018"
}

推荐阅读