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 包,这个选项通常能显著减少导入层面的摩擦。

参考信息

创建于 2026/5/15 更新于 2026/5/27