最近在开发 NodeJS 项目的时候有下面的错误提示信息:
Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead.
问题和解决
我们在 tsconfig.json
的配置文件中添加了 "esModuleInterop": true,
这个配置选项。
这个配置选项将会导致上面的问题。
正是因为上面的配置,我们需要将导入的方法
import * as cors from "cors";
修改为:
import cors from "cors";
有类型声明文件
- 使用import cjs = require(‘cjs’)方法的导入
- 使用import * as cjs from 'cjs’方法的导入,此时cjs相当于exports变量(虽然这能够正常工作,但其实不符合es模块规范,es 模块规范规定 cjs 这个命名空间只能是一个纯对象,但是不能够直接调用)
// 不符合规范的导入方式
import * as Koa from 'koa';
const app = new Koa();
// 编译后的结果
const Koa = require("koa");
const app = new Koa();
那怎么才能使用 import cjs from ‘cjs’ 的语法呢?
首先你需要去除类型检查(允许从没有设置默认导出的模块中默认导入),这可以使用allowSyntheticDefaultImports 配置项做到。
其次你的导出需要有 default 属性,因为 allowSyntheticDefaultImports 只是帮你去掉类型检查,但是并不会影响编译后的代码输出,假设没有 default 属性,虽然可以正常编译,但是在运行时还是会报错的,这就需要 esModuleInterop 配置帮你完成了,因为对于大对数模块而言,并没有default属性。
简单点来说 esModuleInterop 的这个配置选项能够允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。