【升级打怪实录】TS 中 import path from path 竟然报错

149 阅读1分钟

场景

node 环境下有这么一段代码

import path from "path"
// ...
const yamlPath = path.join(process.cwd(), `./config/.${environment}.yaml`)

代码中通过 path.join() 拼接路径,运行后报错: TypeError: Cannot read properties of undefined (reading 'join')

解决方案

  1. TS 配置中设置 esModuleInterop 字段为 true
  2. import path from path 修改为 import * as path from

问题产生原因

import xxx from xxx 属于 ESM 的默认导入语法,对应的导出是默认导出(export default);而 nodejs 的内置模块属于 CommonJS,没有默认导出,所以导致报错。

TS 配置中设置 esModuleInterop 字段为 true 的原理

启用 esModuleInterop 后,会有一个包装函数 __importDefault 将 CommonJS 包装成兼容 ESM 的默认导出。

编译后的代码类似: const path = __importDefault(require('path')).default这样就拥有了 default 属性。

import * as path from 的原理

import * as path from path 属于命名空间导入,将模块的所有导出绑定到一个命名空间对象上,也就可以通过该命名空间对象访问导出的属性和方法了。

对于 ESM 模块,如果它有默认导出 export default 时,通过命名空间导入时,默认导出会绑定到 [[命名空间]].default 属性上。

适用场景

  1. 导入一个没有显式声明为 ESM 的模块时,这种方式最为安全。
  2. ESM 中只有命名导出,没有默认导出,可以方便将所有命名导出一次性导入。

import path from node:path 的作用

这种写法是 nodejs 14.13.0+ 引入的。

这种方式显式指明引入的是 nodejs 的核心模块,限定模块来源,避免与同名第三方模块冲突。