Skip to content
第 6 章 前端 ⏱ 11 分钟阅读

第 6 章:类型别名与联合 ​

学习目标 ​

  • 用 type 创建别名
  • 学会联合类型(Union)与字面量类型
  • 掌握交叉类型(Intersection)
  • 区分 type 和 interface 的使用场景

一、类型别名(type alias) ​

typescript
// 给原始类型起别名
type ID = string | number;
type Callback = (result: number) => void;

// 给对象起别名(等同于 interface)
type User = {
  id: number;
  name: string;
};

// 给联合起别名
type Status = 'success' | 'error' | 'loading';

const id: ID = 'abc-123';
const cb: Callback = (r) => console.log(r);

二、联合类型(Union) ​

一个变量可以是多种类型之一。

typescript
let value: string | number = 'Tom';
value = 123;       // ✅
value = true;      // ❌ Type 'boolean' is not assignable

// 函数参数联合
function print(id: string | number): void {
  console.log(`ID: ${id}`);
}

print(1);          // ✅
print('abc');      // ✅

联合类型需要"收窄" ​

typescript
function print(id: string | number): void {
  console.log(id.toUpperCase());
  // ❌ Property 'toUpperCase' does not exist on type 'number'
}

function print(id: string | number): void {
  if (typeof id === 'string') {
    console.log(id.toUpperCase());  // ✅ 收窄为 string
  } else {
    console.log(id.toFixed(2));     // ✅ 收窄为 number
  }
}

⚠️ 坑 1:联合类型不能直接调"所有分支都有的方法",必须先 typeof / in / instanceof 收窄。

三、字面量类型(Literal Types) ​

typescript
// 字符串字面量
type Direction = 'up' | 'down' | 'left' | 'right';

function move(d: Direction): void {
  console.log(d);
}

move('up');    // ✅
move('side');  // ❌ Argument of type '"side"' is not assignable

// 数字字面量
type Dice = 1 | 2 | 3 | 4 | 5 | 6;
const roll: Dice = 3;

// 布尔字面量
type Bool = true;  // 只能是 true

典型场景:

typescript
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Status = 200 | 404 | 500;

interface Request {
  method: Method;
  url: string;
}

const req: Request = { method: 'GET', url: '/api/users' };

四、可辨识联合(Discriminated Union) ​

typescript
interface LoadingState {
  status: 'loading';
}

interface SuccessState<T> {
  status: 'success';
  data: T;
}

interface ErrorState {
  status: 'error';
  error: string;
}

type State<T> = LoadingState | SuccessState<T> | ErrorState;

function render(state: State<User>): string {
  switch (state.status) {
    case 'loading':
      return '加载中...';
    case 'success':
      return `数据:${state.data.name}`;  // ✅ 收窄到 SuccessState
    case 'error':
      return `错误:${state.error}`;       // ✅ 收窄到 ErrorState
  }
}

⚠️ 坑 2:status 这种字段叫辨识字段(discriminant),必须每种类型都有,且类型不同(常用字面量)。

五、交叉类型(Intersection) ​

类型 A 和 B 合并(&):

typescript
type A = { name: string };
type B = { age: number };

type AB = A & B;  // { name: string; age: number }

const user: AB = { name: 'Tom', age: 18 };

// 函数交叉
type Fn1 = (a: number) => string;
type Fn2 = (b: string) => number;
type FnCombined = Fn1 & Fn2;  // 两个签名都必须实现(其实几乎不可能,慎用)

常见用法:

typescript
// 1. 混入(mixin)
type WithTimestamps = { createdAt: Date; updatedAt: Date };
type Post = { title: string } & WithTimestamps;

// 2. 给已有类型加字段
type UserWithToken = User & { token: string };

六、type 与 interface 的区别 ​

维度typeinterface
对象/函数✅✅
联合/交叉✅❌
字面量✅❌
合并(declare merge)❌✅
继承用 &用 extends
implements✅✅
typescript
// type 不能这样:
type User = { name: string };
type User = { age: number };  // ❌ Duplicate identifier 'User'

// interface 可以合并:
interface User { name: string; }
interface User { age: number; }  // ✅ 自动合并

七、实战:状态机 ​

typescript
type State =
  | { kind: 'idle' }
  | { kind: 'loading' }
  | { kind: 'success'; data: User[] }
  | { kind: 'error'; msg: string };

function render(state: State): string {
  switch (state.kind) {
    case 'idle':    return '未开始';
    case 'loading': return '加载中';
    case 'success': return `共 ${state.data.length} 条`;
    case 'error':   return `失败:${state.msg}`;
  }
}

八、本章小结 ​

要点关键
类型别名type ID = string | number
联合类型string | number,需收窄才能用
字面量'GET' | 'POST' 限定取值范围
可辨识联合每种 case 带不同字面量字段,switch 收窄
交叉类型A & B,合并所有字段
type vs interface对象结构用 interface,联合/字面量用 type

动手练习 ​

  1. 联合类型:写 format(value: string \| number),字符串加引号、数字保留 2 位小数
  2. 字面量状态:用字面量联合定义 TrafficLight = 'red' \| 'yellow' \| 'green'
  3. 可辨识联合:实现 handleEvent(e: ClickEvent \| KeyEvent \| ScrollEvent),根据 kind 区分

下一章:第 7 章:泛型 →

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