Skip to content

D23. Typescript 的模块化

3.1. 🌟 为 JavaScript 编写类型声明文件

3.1.1. 声明文件的编写步骤

核心思想: 通过 .d.ts 文件为 JavaScript 模块添加类型信息,实现类型安全的引用。

步骤 1:创建声明文件

typescript
// my-js-module.d.ts
// 注意:无需实现代码,仅描述类型

步骤 2:定义模块导出

typescript
// 命名导出
export declare function add(a: number, b: number): number;

// 默认导出
export default declare class Calculator {
  multiply(a: number, b: number): number;
}

步骤 3:关联模块tsconfig.json 中包含声明文件:

json
{
  "include": ["src", "my-js-module.d.ts"]
}

3.1.2. 全局变量 vs 模块声明

全局变量声明

typescript
// global.d.ts
declare const globalVar: string; // 声明全局变量
declare function globalFunction(): void; // 声明全局函数

模块化声明

typescript
// module-a.d.ts
export interface Config {
  host: string;
}

export function start(config: Config): void;

TIP

  • 全局变量声明无需 export,直接挂载到全局作用域。
  • 模块声明需通过 import/require 引入。

3.1.3. 实战案例:给第三方库添加类型

场景:第三方库 math-utils.js 未提供类型声明,需手动补全。

javascript
// math-utils.js
function add(a, b) {
  return a + b;
}
function multiply(a, b) {
  return a * b;
}
export { add, multiply };

声明文件 math-utils.d.ts

typescript
// math-utils.d.ts
export declare function add(a: number, b: number): number;
export declare function multiply(a: number, b: number): number;

使用示例

typescript
import { add, multiply } from "./math-utils";

console.log(add(1, 2)); // 合法
// console.log(add("1", 2)); // ❌ 类型错误

3.2. 🌟 export 语句:导出成员与类型

3.2.1. 命名导出与默认导出

命名导出(Named Export)

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

export interface Config {
  precision: number;
}

默认导出(Default Export)

typescript
// calculator.ts
export default class Calculator {
  multiply(a: number, b: number): number {
    return a * b;
  }
}

TIP

  • 命名导出需通过 import { ... } 引入,名称需与导出名一致。
  • 默认导出可任意命名,但需使用 import X from '...'

3.2.2. 导出类型与接口

导出接口

typescript
// types.ts
export interface User {
  id: number;
  name: string;
}

export type Status = "active" | "inactive";

导出类型别名

typescript
// utils.ts
export type Callback = (result: any) => void;

export function process(data: any, callback: Callback): void {
  // ...
}

3.2.3. 导出合并与扩展

接口合并

typescript
// module-a.ts
export interface User {
  id: number;
}

// module-b.ts
export interface User {
  name: string;
}

// 合并后:User = { id: number, name: string }

类型扩展

typescript
// base.ts
export class BaseService {
  start(): void {}
}

// extended.ts
export class Service extends BaseService {
  stop(): void {}
}

3.3. 🌟 import 语句:精准导入与类型隔离

3.3.1. 导入默认导出与命名导出

导入命名导出

typescript
import { add, Config } from "./math";

const result = add(1, 2); // 合法
const config: Config = { precision: 2 }; // 合法

导入默认导出

typescript
import Calculator from "./calculator";

const calc = new Calculator();
console.log(calc.multiply(3, 4)); // 12

混合导入

typescript
import Calculator, { add } from "./module"; // 同时导入默认和命名导出

3.3.2. 类型导入的 type 语法

区分值和类型

typescript
// 导入值和类型
import { User } from "./types"; // 同时导入类型和值(若存在)
import type { User } from "./types"; // 仅导入类型,不打包到 JS

TIP

  • import type 可避免打包时引入无用的运行时代码。
  • 类型导入无需 declare,直接使用接口/类型别名。

3.3.3. 坑位警示:默认导出的陷阱

陷阱 1:命名错误

typescript
// 错误示例:将默认导出命名为接口
import User from "./user"; // ❌ 默认导出是类或函数,不能直接当类型使用

// 正确写法:
import User, { UserType } from "./user";
// UserType 是接口,User 是默认导出的类

陷阱 2:类型与值冲突

typescript
// user.ts
export default class User {}
export type UserConfig = { /* ... */ };

// 其他文件
import User, { UserConfig } from "./user"; // User 是类,UserConfig 是类型

注意

默认导出的名称不能与命名导出的类型重名!

typescript
// 错误示例:
export default class User {}
export type User = "admin" | "guest"; // ❌ 类型与默认导出冲突

知识回顾

  1. 声明文件
    • 通过 .d.ts 为 JavaScript 添加类型,支持全局变量和模块声明。
    • 使用 declare 关键字定义类型,无需实现代码。
  2. export 语法
    • 命名导出:export function/class/variable
    • 默认导出:export default
    • 接口支持合并扩展。
  3. import 语法
    • 区分默认导出和命名导出的语法。
    • 使用 import type 隔离类型导入,避免打包冗余。

课后练习

  1. (单选)以下哪种写法可以正确导入默认导出的 Calculator 类? A. import Calculator from "./calculator"; B. import { Calculator } from "./calculator"; C. import * as Calculator from "./calculator"; D. import { default as Calculator } from "./calculator";

  2. (填空)为以下 JavaScript 函数编写类型声明:

    javascript
    // math.js
    export function subtract(a, b) {
      return a - b;
    }

    声明文件代码:

    typescript
    export declare function subtract(____, ____): ____;
  3. (编码)修复以下代码的类型错误:

    typescript
    // user.ts
    export default class User {
      id!: number;
    }
    export type UserRoles = "admin" | "user";
    
    // main.ts
    import User, { UserRoles } from "./user"; // ❌ 类型冲突
    // 请修改导入语句

扩展阅读

Built by Vitepress | Apache 2.0 Licensed