TypeScript 模块
在现代 JavaScript 和 TypeScript 开发中,模块(Modules)是组织代码、管理依赖和避免污染全局作用域的核心机制。从 ES6 (ECMAScript 2015) 开始,JavaScript 原生支持了模块系统,而 TypeScript 完全兼容并扩展了这一系统。
对于所有新项目,模块是推荐的代码组织方式。
什么是模块?
在 TypeScript 中,任何包含顶级 import 或 export 声明的文件都被视为一个模块。每个模块都有自己的作用域,模块中声明的变量、函数、类等在模块外部是不可见的,除非它们被明确地导出。
export:导出模块成员
你可以使用 export 关键字来使模块中的成员可以被其他模块访问。
math.ts
// 导出一个常量
export const PI = 3.14159;
// 导出一个接口
export interface Calculation {
(x: number, y: number): number;
}
// 导出一个函数
export function add(x: number, y: number): number {
return x + y;
}
// 导出一个类
export class Subtract {
calculate(x: number, y: number): number {
return x - y;
}
}import:导入模块成员
你可以使用 import 关键字来从另一个模块中导入其导出的成员。
app.ts
// 从 './math' 模块导入指定的成员
import { PI, add, Subtract } from './math';
console.log(PI); // 3.14159
let result = add(10, 5);
console.log(result); // 15
let subtractor = new Subtract();
console.log(subtractor.calculate(20, 8)); // 12默认导出 (Default Exports)
每个模块还可以有一个“默认”导出。默认导出在导入时语法更简洁。一个模块只能有一个默认导出。
calculator.ts
export default class Calculator {
add(x: number, y: number): number {
return x + y;
}
// ...其他方法
}
// 你仍然可以有其他的命名导出
export const version = "1.0";导入默认导出
导入默认导出时,你可以给它指定任意的名称。
main.ts
// 导入默认导出的 Calculator 类,并命名为 MyCalc
import MyCalc, { version } from './calculator';
const calc = new MyCalc();
console.log(calc.add(5, 5)); // 10
console.log(`Version: ${version}`); // Version: 1.0其他导入/导出语法
导入所有成员
你可以使用 * as name 的语法将一个模块的所有导出成员导入到一个对象中。
import * as math from './math';
console.log(math.PI);
let res = math.add(2, 3);重新导出
有时候,你可能想创建一个模块,它聚合了其他几个模块的导出。你可以导入后再导出,或者直接重新导出。
utils.ts
// 重新导出 stringUtils.ts 中的所有内容
export * from './stringUtils';
// 重新导出 numberUtils.ts 中的 'isEven'
export { isEven } from './numberUtils';模块解析
当你说 import { a } from "moduleB" 时,TypeScript 编译器需要知道 moduleB 指的是哪个文件。这个过程称为模块解析。
TypeScript 支持两种主要的模块解析策略:
- Classic (经典): 早期版本的默认策略,现在很少使用。
- Node: Node.js 使用的解析策略,也是现在绝大多数项目的标准。它会查找相对路径(
./moduleB)或在node_modules文件夹中查找非相对路径(moduleB)。
你可以在 tsconfig.json 文件中通过 moduleResolution 选项来配置这个策略。
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "Node"
}
}模块格式
TypeScript 代码最终需要被编译成特定模块格式的 JavaScript,以便在目标环境(如浏览器或 Node.js)中运行。常见的模块格式包括:
- CommonJS: Node.js 使用的主要格式。
- AMD (Asynchronous Module Definition): 在 RequireJS 等库中使用。
- ES6 / ES2015: 现代浏览器和打包工具支持的原生模块格式。
你可以在 tsconfig.json 的 module 选项中指定输出的模块格式。对于现代 Web 开发,通常会设置为 ESNext,然后由打包工具(如 Vite 或 Webpack)处理成浏览器兼容的代码。