TypeScript 联合类型
有些数据"既可能是这种类型、也可能是那种类型"。联合类型(Union Types)用 | 把多个类型"或"起来,让变量只能在这些类型里取值。它是表达可选分支的基础,也是后面学类型收窄(Narrowing)、可辨识联合的起点。
基本写法
let id: string | number; // id 只能是 string 或 number
id = "A1001"; // 合法
id = 1001; // 合法
// id = true; // 报错:boolean 不在联合范围内
console.log(id); // 输出:1001
为什么要收窄
联合类型只允许调用"所有成员都有"的操作。想让字符串用 .length、数字用 .toFixed,必须先判断类型,这叫类型收窄:
function getLen(v: string | number): number {
if (typeof v === "string") {
return v.length; // 此分支收窄为 string
}
return v.toString().length; // 此分支收窄为 number
}
console.log(getLen("hello")); // 输出:5
console.log(getLen(12345)); // 输出:5
字面量联合:把取值范围写死
选项、开关、状态码这类场景,直接把允许的字面量列出来:
type Status = "success" | "error" | "pending";
let s: Status = "success";
// s = "done"; // 报错:没有 "done" 这个取值
type Dice = 1 | 2 | 3 | 4 | 5 | 6; // 数字字面量同样可以
function tip(st: Status): string {
return st === "success" ? "成功" : "未成功";
}
console.log(tip("error")); // 输出:未成功
数组、可空与对象联合
// 数组里每一项都可能是 number 或 string
const mixed: (number | string)[] = [1, "a", 2];
console.log(mixed); // 输出:[1, 'a', 2]
// 联合 undefined 表达"可能查不到"
function findUser(id: number): { name: string } | undefined {
return id === 1 ? { name: "张三" } : undefined;
}
console.log(findUser(1)); // 输出:{ name: '张三' }
console.log(findUser(9)); // 输出:undefined
可辨识联合(Discriminated Union)
给每个分支一个唯一的 kind 字段做"判别式",switch 之后 TS 自动收窄到对应结构:
type Circle = { kind: "circle"; radius: number };
type Square = { kind: "square"; side: number };
type Shape = Circle | Square;
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2; // 此分支只认 radius
case "square":
return shape.side ** 2; // 此分支只认 side
}
}
console.log(area({ kind: "square", side: 3 }).toFixed(1)); // 输出:9.0
小结
联合类型用 | 表达"或"关系,核心套路是"先收窄、再操作":基本值用 typeof 判断,对象用 kind + switch 收窄。配合字面量类型,还能把取值范围限制为少数几个固定值。