目录

  1. 模块概述
  2. 为什么使用模块
  3. 模块的基本语法
  4. 默认导出(Default Export)
  5. 命名导出(Named Export)
  6. 模块的别名与重命名
  7. 使用 export * 进行批量导出
  8. TypeScript 模块解析策略
  9. 模块 vs 命名空间
  10. 模块的最佳实践
  11. 参考资料

1. 模块概述

在 TypeScript 中,模块(Module) 是代码的独立单元,它可以封装变量、类、函数等,并通过 export 关键字导出,在其他文件中使用 import 关键字引入。

模块的特点:

  • 作用域独立:模块中的变量不会污染全局作用域。
  • 可复用:模块可以在多个文件或项目中复用,提高代码的组织性和维护性。
  • 依赖管理:可以通过 import 导入模块,而无需手动管理文件依赖。

2. 为什么使用模块

在 JavaScript 早期,开发者通常使用全局变量或 IIFE(立即执行函数)来管理代码。但这种方法容易造成命名冲突全局作用域污染,不利于代码组织。

TypeScript 提供了 ES6 模块系统 来解决这些问题,并且支持:

  • 按需加载:只有导入的模块才会被加载,优化性能。
  • 清晰的依赖关系:不同模块之间的依赖清晰可见。
  • 代码复用:模块化代码可以跨文件、跨项目使用。

3. 模块的基本语法

(1)导出模块

在 TypeScript 中,可以使用 export 关键字导出变量、函数、类或接口。

📌 math.ts

export const PI = 3.14;

export function add(a: number, b: number): number {
    return a + b;
}

export class Calculator {
    multiply(a: number, b: number): number {
        return a * b;
    }
}

(2)导入模块

在其他文件中,可以使用 import 关键字导入模块。

📌 app.ts

import { PI, add, Calculator } from "./math";

console.log(PI); // 3.14
console.log(add(2, 3)); // 5

const calc = new Calculator();
console.log(calc.multiply(4, 5)); // 20

注意:

  • 必须使用 import { ... } 来引入导出的成员。
  • 需要使用 相对路径(如 ./math),否则 TypeScript 可能找不到模块。

4. 默认导出(Default Export)

TypeScript 允许使用 export default 来导出单个默认值。

📌 logger.ts

export default function log(message: string) {
    console.log(`Log: ${message}`);
}

📌 app.ts

import log from "./logger";

log("Hello TypeScript!"); // Log: Hello TypeScript!

特点:

  • 每个模块只能有一个 export default
  • 导入时可以使用任意名称(如 log)。
  • 更适合导出单个类或函数

5. 命名导出(Named Export)

命名导出允许在一个模块中导出多个变量、函数或类。

📌 utils.ts

export function formatDate(date: Date): string {
    return date.toISOString().split("T")[0];
}

export function formatNumber(num: number): string {
    return num.toFixed(2);
}

📌 app.ts

import { formatDate, formatNumber } from "./utils";

console.log(formatDate(new Date())); // 2025-03-22
console.log(formatNumber(123.456)); // "123.46"

特点:

  • 可以在一个模块中导出多个成员。
  • 必须使用 {} 结构化导入。

6. 模块的别名与重命名

在导入模块时,可以使用 as 关键字进行重命名,避免命名冲突。

📌 math.ts

export function add(a: number, b: number): number {
    return a + b;
}

export function subtract(a: number, b: number): number {
    return a - b;
}

📌 app.ts

import { add as sum, subtract as diff } from "./math";

console.log(sum(10, 5)); // 15
console.log(diff(10, 5)); // 5

适用于:

  • 避免命名冲突。
  • 提高代码可读性。

7. 使用 export * 进行批量导出

如果需要从一个模块导入所有导出的内容,可以使用 export *

📌 math.ts

export const PI = 3.14;
export function add(a: number, b: number): number {
    return a + b;
}

📌 index.ts

export * from "./math";

📌 app.ts

import * as MathUtils from "./index";

console.log(MathUtils.PI); // 3.14
console.log(MathUtils.add(2, 3)); // 5

适用于:

  • 批量导出 模块成员,提高组织性。
  • 避免多个 import 语句

8. TypeScript 模块解析策略

TypeScript 解析模块时,有两种策略:

  1. Node.js 解析方式(默认)
    • 根据 moduleResolution 选项查找 node_modules 目录。
    • 支持 .ts.tsx.js 文件扩展名。
  2. 经典解析方式
    • 适用于旧版 TypeScript 项目,优先查找 baseUrl 目录。

9. 模块 vs 命名空间

特性模块(Module)命名空间(Namespace)
作用范围文件级别全局
使用方式import/exportnamespace 关键字
适用场景现代前端/后端开发传统大型项目
依赖管理通过 import 自动解析需要 /// <reference>

📌 推荐:现代 TypeScript 项目中,优先使用模块,而不是命名空间


10. 模块的最佳实践

优先使用 ES6 模块 而非 命名空间
一个文件最好只导出一个默认值,或者使用命名导出组织多个功能
使用 import * as alias 组织大型模块,避免命名冲突
结合 export * 进行批量导出,提高代码的可维护性


11. 参考资料


总结

  • TypeScript 模块用于组织代码,支持 import/export 进行依赖管理。
  • export default 适用于导出单个值,named export 适用于导出多个成员。
  • import * as alias 可用于批量导入,export * 可用于批量导出。
  • 现代项目推荐使用模块,而不是命名空间,以便与 ES6 生态兼容。 🚀