TypeScript 中 module 与 moduleResolution 的关系

解释为什么 module 与 moduleResolution 总是一起出现,但一个主要管输出模块格式,另一个主要管模块解析规则。

#tech / dev #resource / typescript #type / synthesis #status / growing

[!info] related notes

TypeScript 中 module 与 moduleResolution 的关系

范围

这篇笔记专门解决一个常见混淆:为什么 modulemoduleResolution 总一起改,但它们并不是同一个选项。

为什么要放在一起理解

它们都和“模块”有关,所以最容易被误解成:

  • 一个控制 ESM / CJS
  • 一个也控制 ESM / CJS

其实更准确的理解是:

  • module 更偏“输出成什么”
  • moduleResolution 更偏“怎么找模块”

依赖路径 / 调用链 / 演进链

module

决定最终 JavaScript 更接近:

  • import / export
  • 还是 require / module.exports

moduleResolution

决定看到:

import { foo } from "./foo";

时,TypeScript 按哪套规则去解析。

它们为什么又不能完全分开

node16 / nodenext 模式下,最终输出到底会是 import 还是 require,会进一步影响 TypeScript 该用哪一套 Node 条件去解析 package exports。

因此两者虽然分工不同,但会互相耦合。

对比与易混淆点

典型组合

  • Node 项目:
    • module: "nodenext"
    • moduleResolution: "nodenext"
  • bundler 项目:
    • module: "esnext"
    • moduleResolution: "bundler"

典型误配

  • module: "esnext" + moduleResolution: "node16"

TypeScript 5.2 之后对此类不匹配配置更严格,很多情况下会直接报配置错误。

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