TypeScript 中的模块(Modules)详解

模块(Modules) 是现代 TypeScript 项目中组织和管理代码的最主要方式。它基于 ES6 的 importexport 语法(也称为 ES Modules 或 ESM),完全取代了旧的命名空间(namespace)。模块系统让代码具备作用域隔离、按需加载、tree-shaking 等优势,是当前所有主流框架(React、Vue、Angular、NestJS、Next.js 等)的标准做法。

1. 基本导出与导入

a. 导出(export)
// file: utils.ts
export function sum(a: number, b: number): number {
  return a + b;
}

export const PI = 3.14159;

export interface User {
  name: string;
  age: number;
}

export class Calculator {
  multiply(x: number, y: number): number {
    return x * y;
  }
}

// 默认导出(一个模块只能有一个)
export default function greet(name: string): string {
  return `Hello, ${name}!`;
}
b. 导入(import)
// file: main.ts
import greet from "./utils";  // 默认导入

import { sum, PI, User, Calculator } from "./utils";  // 命名导入
import { sum as add } from "./utils";                 // 重命名

import * as Utils from "./utils";  // 导入所有为命名空间对象

greet("Alice");              // "Hello, Alice!"
console.log(sum(2, 3));      // 5
console.log(Utils.PI);

let calc = new Calculator();
calc.multiply(4, 5);

2. 导出方式总结

方式语法示例说明
命名导出export function fn() {}可导出多个
默认导出export default class MyClass {}一个模块只能一个
重新导出(Re-export)export { name } from "./other";聚合模块
全部重新导出export * from "./utils";导出其他模块的所有(不包括默认导出)
重命名导出export { sum as add } from "./math";

3. 模块路径与解析

  • 相对路径"./utils""../models/user"
  • 绝对路径(需配置 baseUrlpaths):
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./src",                  // 根目录
    "paths": {
      "@utils/*": ["utils/*"],           // 别名
      "@components/*": ["components/*"]
    }
  }
}

使用:

import { sum } from "@utils/math";
import Button from "@components/Button";

4. 模块模式(Module Mode)

tsconfig.json 中配置:

配置值输出格式适用环境
"ESNext""ES2022"原生 ES Modules现代浏览器、Vite、Deno、Bun
"CommonJS"require/module.exportsNode.js(传统)
"AMD" / "UMD" / "System"旧模块系统老项目

推荐:现代项目统一使用 "ESNext" + "moduleResolution": "node""nodenext"

5. 动态导入(Dynamic Import)—— 按需加载

返回 Promise,适合代码分割、懒加载:

// 静态导入(打包时一起加载)
import { heavyFunction } from "./heavy";

// 动态导入(运行时加载)
async function loadHeavy() {
  const module = await import("./heavy");
  module.heavyFunction();
}

button.addEventListener("click", loadHeavy);

6. 类型声明模块(Declaration Files)

为非 TS 文件(如 .js、第三方库)提供类型:

// file: declarations/jquery.d.ts
declare module "jquery" {
  export default function $(selector: string): any;
}

// 使用
import $ from "jquery";
$("#app").html("Hello");

或全局声明:

// file: globals.d.ts
declare global {
  interface Window {
    myGlobalVar: string;
  }
}

7. 侧边模块增强(Module Augmentation)

扩展第三方库的类型(常见于 lodash、express 等):

// file: types/express.d.ts
import "express";

declare module "express" {
  interface Request {
    user?: { id: number; name: string };
  }
}

// 现在所有 express Request 都有 user 属性类型提示

8. 常见模块使用场景

场景推荐方式
工具函数一个文件导出多个函数
React 组件export default function Component()
类型/接口单独文件导出多个 interface/type
常量配置export const CONFIG = { ... }
聚合导出(barrel)index.tsexport * from "./xxx"
Node.js 服务端"module": "ESNext" + .mjs"type": "module"

9. 最佳实践建议

建议说明
一个文件一个责任每个文件导出相关的一组内容
优先默认导出组件React/Vue 等组件用 export default
类型单独文件interfaces/types 放 types/ 或单独 .d.ts
使用路径别名配置 @utils/* 等,提高可读性
避免循环依赖模块相互 import 会导致问题
barrel 文件谨慎使用export * from 过多影响 tree-shaking
开启 "isolatedModules": true确保兼容 Babel、esbuild 等工具

小结:模块 vs 命名空间

特性模块 (import/export)命名空间 (namespace)
现代推荐强烈推荐已过时
作用域文件级隔离全局或嵌套
加载方式静态/动态,按需脚本加载
tree-shaking支持不支持
声明文件支持常用于旧库

结论:在 2025 年的 TypeScript 开发中,所有新项目都应使用 ES 模块系统。命名空间仅用于维护旧代码或特定声明文件场景。

如果您想看实际项目结构示例(如 React + Vite 的模块组织、Next.js 的页面模块、Node.js 的服务模块),或者想了解如何配置 tsconfig 支持模块,请告诉我!

文章已创建 3383

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部