TypeScript 中的 baseUrl 与 paths

说明 baseUrl 与 paths 为什么常被一起提及、它们的职责如何不同,以及现代项目为什么更倾向于减少对 baseUrl 的依赖。

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

[!info] related notes

TypeScript 中的 baseUrl 与 paths

范围

这篇笔记不再分别定义 baseUrlpaths 的全部细节,而是解释为什么它们总被放在一起讨论。

为什么要放在一起理解

它们经常一起出现,是因为历史上很多项目会这样写:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@app/*": ["app/*"]
    }
  }
}

但它们的职责并不相同:

  • baseUrl 更偏“给裸模块一个额外查找根”
  • paths 更偏“把某个模式映射到一组目标路径”

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

旧习惯

如果你的 baseUrl 只是为了给 paths 提供公共前缀,更推荐改成:

{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"],
      "@lib/*": ["./src/lib/*"]
    }
  }
}

这是因为过去 paths 常和 baseUrl 一起出现。

现代趋势

从 TypeScript 4.1 起,paths 已不再要求必须配置 baseUrl

因此现代项目的趋势更像:

  • 如果只是 alias,优先把路径写显式
  • 尽量别再让 baseUrl 额外参与裸模块解析

边界与易混淆点

“经常一起用”不等于“应该永远一起写”

这是最常见的历史惯性误解。

拆开后更容易判断该改谁

很多时候你真正该处理的是:

  • baseUrl 参与裸模块解析的问题

或者:

  • paths 与运行时 alias 不一致的问题

把两者分开理解,排障会明显更快。

参考信息

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