TS 中的模块声明

大哥帮我讲解下,TS 中的模块声明
最新回答
月影依风

2026-10-30 15:57:30

在 TypeScript 中,模块声明用于为非代码资源(如 SVG、GraphQL 文件等)提供类型支持,解决 IDE/TSC 报错“无法找到模块”的问题。 以下是关键点解析:

1. 模块的定义与作用
  • 模块的判定:在 TypeScript/JavaScript 中,任何包含顶级 import 或 export 语句的文件被视为模块;否则为脚本。模块在自身作用域内执行,避免全局命名空间污染。
  • 模块化的优势:通过显式导出内容,消费者可精准导入所需功能,提升代码可维护性。
2. 模块解析策略

TypeScript 提供两种模块解析策略,通过 compilerOptions.moduleResolution 配置:

  • 经典(Classic):默认策略,向后兼容旧版本。适用于非 CommonJS 环境。
  • 节点(Node):模拟 Node.js 的 CommonJS 解析行为,支持 .ts 和 .d.ts 文件的额外检查。
  • 现代策略(如 NodeNext 或 Bundler):

    NodeNext:匹配 Node.js 的 ESM 行为,读取 package.json 的 "type" 字段决定使用 CommonJS 或 ESM。

    Bundler:适用于打包工具(如 Webpack、Vite),支持路径别名和裸模块说明符。

3. 模块声明的核心场景

当导入非代码资源(如 SVG、GraphQL)时,TypeScript 无法自动推断类型,需通过声明文件(.d.ts)手动定义模块类型。

示例:声明 SVG 模块
  1. 创建声明文件:在项目中添加 svg.d.ts(或 global.d.ts):

    declare module '*.svg' { const content: string; export default content;}

    此声明告知 TypeScript:所有以 .svg 结尾的导入应被视为返回 string 类型的模块。

  2. 配置 tsconfig.json:确保包含声明文件的目录在 TypeScript 的搜索路径中(通常通过 include 或 files 配置)。

4. 路径映射与别名

通过 tsconfig.json 的 paths 选项简化模块导入路径:

{ "compilerOptions": { "module": "esnext", "moduleResolution": "bundler", "paths": { "@shared/*": ["./src/shared/*"] } }}
  • 作用:将 @shared/ 开头的导入映射到 ./src/shared/ 目录。
  • 注意:路径别名需打包工具或运行时支持,否则可能导致执行错误。
5. 裸模块说明符(Bare Specifiers)
  • 定义:非相对路径(如 import { ... } from 'react')的模块名称,通常指向 node_modules 或配置的路径。
  • 解析优先级:裸模块名称的解析优先级高于从 node_modules 查找,可通过 baseUrl 和 paths 自定义映射。
6. 编译后的 JavaScript 输出控制
  • target:指定输出的 JavaScript 版本(如 ES2015、ESNext),确保兼容性。
  • module:控制输出的模块系统(如 CommonJS、ESM、ESNext),需与目标运行时或打包工具匹配。
7. 常见问题与解决
  • 错误:[ts] Cannot find module './logo.svg'原因:TypeScript 默认不支持 SVG 导入,需声明模块类型。解决:创建 .d.ts 文件并声明 *.svg 模块。

  • 路径别名失效检查:tsconfig.json 的 paths 配置是否正确,打包工具是否支持别名。

总结

TypeScript 的模块声明通过 .d.ts 文件为非代码资源提供类型支持,结合模块解析策略和路径映射,可高效解决模块导入问题。关键步骤包括:

  • 创建声明文件定义模块类型。
  • 配置 tsconfig.json 的 moduleResolution 和 paths。
  • 确保编译选项(target、module)与目标环境匹配。