模块解析

模块解析是编译器查找模块的过程。TypeScript 支持两种模块解析策略:Classic 和 Node。理解模块解析机制有助于解决模块导入问题。

Classic 策略

Classic 是 TypeScript 的默认策略,主要用于 AMD、SystemJS 等旧模块系统。

相对路径导入:

import { User } from "./user"

解析顺序:

  1. 查找 ./user.ts
  2. 查找 ./user.d.ts

非相对路径导入:

import { User } from "user"

解析顺序:

  1. 从当前目录向上查找 user.tsuser.d.ts

Node 策略

Node 策略模拟 Node.js 的模块解析机制,是现代项目的推荐选择。

相对路径导入:

import { User } from "./user"

解析顺序:

  1. 查找 ./user.ts
  2. 查找 ./user.tsx
  3. 查找 ./user.d.ts
  4. 查找 ./user/package.json 中的 types 字段
  5. 查找 ./user/index.ts
  6. 查找 ./user/index.tsx
  7. 查找 ./user/index.d.ts

非相对路径导入:

import { User } from "user"

解析顺序:

  1. 查找 node_modules/user.ts
  2. 查找 node_modules/user.tsx
  3. 查找 node_modules/user.d.ts
  4. 查找 node_modules/user/package.json 中的 types 字段
  5. 查找 node_modules/@types/user.d.ts
  6. 向上查找父目录的 node_modules

配置模块解析

tsconfig.json 中配置模块解析策略。

{
  "compilerOptions": {
    "moduleResolution": "node"
  }
}

Node 策略是现代项目的推荐选择。

路径映射

路径映射可以简化模块导入路径。

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

使用路径映射导入模块。

import { formatDate } from "@utils/format"
import { Button } from "@components/Button"

基础路径

baseUrl 设置模块解析的基础路径。

{
  "compilerOptions": {
    "baseUrl": "./src"
  }
}

所有非相对路径导入都从 baseUrl 开始解析。

import { User } from "models/user"

解析为 ./src/models/user.ts

根目录

rootDirs 设置多个根目录,编译器将它们视为一个目录。

{
  "compilerOptions": {
    "rootDirs": ["src", "generated"]
  }
}

可以从任意根目录导入模块。

import { User } from "./models/user"

编译器会在 src/models/user.tsgenerated/models/user.ts 中查找。

模块解析追踪

使用 traceResolution 选项追踪模块解析过程。

{
  "compilerOptions": {
    "traceResolution": true
  }
}

编译时会输出详细的模块解析日志,帮助调试导入问题。

常见问题

模块解析常见问题:

  1. 找不到模块:检查路径是否正确,文件是否存在
  2. 类型定义缺失:安装 @types/xxx
  3. 路径映射错误:检查 paths 配置是否正确
  4. 扩展名问题:TypeScript 默认不查找 .js 文件

实际应用

配置合理的模块解析策略可以提高开发效率。

{
  "compilerOptions": {
    "moduleResolution": "node",
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"],
      "@types/*": ["src/types/*"]
    }
  }
}

使用别名导入模块,代码更加清晰。

import { User } from "@/models/user"
import { Button } from "@components/Button"
import { formatDate } from "@utils/format"
import type { ApiResponse } from "@types/api"

小结

模块解析是编译器查找模块的过程。TypeScript 支持 Classic 和 Node 两种解析策略,推荐使用 Node 策略。路径映射可以简化模块导入路径。baseUrl 设置基础路径,rootDirs 设置多个根目录。理解模块解析机制有助于解决模块导入问题。