TypeScript 中的 esModuleInterop
说明 esModuleInterop 如何让 TypeScript 更平滑地消费 CommonJS 包,以及它为什么会连带开启 allowSyntheticDefaultImports。
#tech / dev
#resource / typescript
#type / concept
#status / growing
[!info] related notes
TypeScript 中的 esModuleInterop
一句话定义
esModuleInterop 用来改善 TypeScript 对 CommonJS 与 ES module 混用场景的兼容行为。
核心机制 / 工作原理
官方文档指出,这个选项主要修正两类不理想的假设:
- namespace import 被当成可调用值
- CommonJS 模块默认导入的行为不够接近真实生态
当配置:
{
"compilerOptions": {
"esModuleInterop": true
}
}
时,TypeScript 会调整 emit 和类型理解方式,让从 CommonJS 包做默认导入这件事更平滑。
同时,它还会自动开启:
allowSyntheticDefaultImports
可以继续看:
最小例子 / 最小场景
{
"compilerOptions": {
"esModuleInterop": true
}
}
这时很多 CommonJS 生态下常见的写法会更顺手,例如:
import _ from "lodash";
边界与易混淆点
它不是“把项目切换成 ESM”
esModuleInterop 处理的是:
- 模块互操作体验
而不是直接决定项目最终输出是不是 ESM。
真正决定输出模块格式的仍然是:
module
它和 bundler 的“能跑”不是一回事
有些 bundler、Babel 或运行时工具链即使没有这个选项,也能把默认导入跑起来。
但 TypeScript 自己如何检查、如何 emit,仍然受 esModuleInterop 影响。
它常见于 CJS 依赖很多的项目
如果项目里大量消费历史 CommonJS 包,这个选项通常能显著减少导入层面的摩擦。
参考信息
- TSConfig
esModuleInterop: https://www.typescriptlang.org/tsconfig/esModuleInterop.html