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 + tsxtsx 原生支持读取 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/打包器的别名插件让运行时与构建期都生效,大型工程会清爽许多。

笔记加载中…