Skip to content
第 15 章 前端 ⏱ 10 分钟阅读

第 15 章:模块与命名空间 ​

学习目标 ​

  • 理解 ES Module 与 TS 模块的关系
  • 学会 import / export 的多种写法
  • 掌握 namespace 的使用场景
  • 理解声明合并与模块解析

一、ES Module 基础 ​

typescript
// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

export const PI = 3.14;

export default class Calculator {
  // ...
}
typescript
// app.ts
import Calculator, { add, PI } from './math';

console.log(add(1, 2));
console.log(PI);
new Calculator();

二、import 多种写法 ​

typescript
// 1. 默认导入
import Calculator from './math';

// 2. 命名导入
import { add, PI } from './math';

// 3. 重命名
import { add as sum, PI as PIValue } from './math';

// 4. 全部导入为命名空间
import * as math from './math';
math.add(1, 2);

// 5. 仅类型导入(编译后擦除,体积更小)
import type { User } from './types';

// 6. 混合
import Calculator, { type User, add } from './math';

⚠️ 坑 1:import type 是 TS 5.0 的优化,可以和值混合导入,避免意外把类型当作值用。Vite 项目一定要用 verbatimModuleSyntax: true 才能正确擦除类型导入。

三、export 多种写法 ​

typescript
// 1. 命名导出
export const PI = 3.14;
export function add() {}

// 2. 批量
const A = 1;
const B = 2;
export { A, B };

// 3. 默认导出(每个模块只能有一个)
export default class Foo {}

// 4. 重命名导出
export { add as sum };

// 5. re-export(转发)
export { add, PI } from './math';
export * from './math';   // ⚠️ 危险:全部转发,污染命名空间

⚠️ 坑 2:export * 不转发 default,需要单独 export { default } from ...。

四、模块解析策略 ​

tsconfig.json:

json
{
  "compilerOptions": {
    "moduleResolution": "node" | "bundler" | "node16" | "nodenext"
  }
}

推荐:

  • Vite/webpack → "bundler"
  • Node.js 项目 → "node16" 或 "nodenext"

五、命名空间(namespace) ​

typescript
namespace Validation {
  export interface StringValidator {
    isValid(s: string): boolean;
  }

  export class LettersOnlyValidator implements StringValidator {
    isValid(s: string): boolean {
      return /^[A-Za-z]+$/.test(s);
    }
  }
}

const validator: Validation.StringValidator = new Validation.LettersOnlyValidator();
validator.isValid('Hello');  // true

嵌套:

typescript
namespace A {
  export namespace B {
    export const x = 1;
  }
}

console.log(A.B.x);  // 1

⚠️ 坑 3:namespace 是老的组织代码方式,现代项目优先用 ES Module,namespace 主要用于类型声明文件和全局类型扩展。

六、namespace vs ES Module ​

维度namespaceES Module
标准TS 私有ECMAScript
文件通常多文件合并单文件
浏览器不能直接用配合打包器可
适用场景全局声明、类型扩展现代代码组织

七、全局类型声明 ​

typescript
// global.d.ts
declare global {
  interface Window {
    myApp: { version: string };
  }

  const VERSION: string;
}

export {};

⚠️ 坑 4:全局声明文件必须有 export {} 才被当作模块,否则 declare global 不生效。

八、动态导入 ​

typescript
async function loadMath(): Promise<void> {
  const math = await import('./math');
  console.log(math.add(1, 2));
}

loadMath();

九、本章小结 ​

要点关键
import 类型import type 编译期擦除,推荐
export 类型命名 / 默认 / 重命名 / re-export
模块解析bundler / node16 / nodenext
namespace老的代码组织,优先用 ES Module
declare global全局声明,必须有 export {}
动态导入await import('./module')

动手练习 ​

  1. 多文件:建 user.ts(导出接口)、app.ts(导入使用)
  2. 类型导入:用 import type 单独导入 User 类型,看编译后产物大小
  3. namespace 实战:用 namespace 组织多个 validator 类

下一章:第 16 章:声明文件 →

本站基于 VitePress 构建 · 由 StackHub 团队维护