TypeScript 路径映射
路径映射(paths)是 tsconfig 中的一项配置,它让我们用短别名导入深层模块,告别一长串 ../../../。当项目结构复杂、目录频繁调整时,合理使用别名能大幅提升代码的可读性与可维护性。
为什么需要路径映射
观察下面的相对导入,层级一深就很难一眼看出它指向哪里:
// 丑:难以阅读,目录一调整就要大范围改动
import { getUser } from "../../../models/user";
import { formatTime } from "../../../../utils/time";
路径映射让我们用 @/、@utils/ 这样的"虚拟根目录"来写导入,语义清晰,移动文件后也无需改动引用。
基础配置:baseUrl 与 paths
路径映射在 tsconfig.json 的 compilerOptions 中配置,核心是 baseUrl 与 paths 两个字段:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@utils/*": ["src/utils/*"]
}
}
}
- baseUrl 是所有非相对导入的解析基准目录,通常设为项目根目录
.。 - paths 的键是"别名模板",值是真实路径数组(可写多个,依次尝试解析)。
通配符 * 的替换规则
* 是通配符,会捕获键中 * 之后的内容,并替换进目标路径:
import { User } from "@/models/user"; // @/* 捕获 models/user,映射到 src/models/user
再看几个多级例子,替换规则与 glob 类似:
import { http } from "@/core/http"; // -> src/core/http
import { isMobile } from "@utils/device"; // -> src/utils/device
import type { Book } from "@/models/book"; // 类型导入同样支持别名
注意 paths 只影响编译期解析,tsc 不会改写产物中的导入路径。
运行时如何识别别名
Node.js 与打包工具默认不认 @/,需要额外配置,常用方案对照:
| 场景 | 方案 |
|---|---|
| Node + ts-node | 安装 tsconfig-paths,并在启动时注册 |
| Node + tsx | tsx 原生支持读取 tsconfig 的 paths |
| Vite | 配置 resolve.alias,与 tsconfig 保持一致 |
| webpack | 配置 resolve.alias |
| Jest | 配置 moduleNameMapper |
以 Vite 为例,需保持与 tsconfig 一致:
import { fileURLToPath, URL } from "node:url";
export default {
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
};
小结
路径映射通过 baseUrl 与 paths 让导入告别 ../../../,用"别名 + 通配符"表达模块域;再配合 ts-node/打包器的别名插件让运行时与构建期都生效,大型工程会清爽许多。