TypeScript类型守卫与可辨识联合详解一
类型守卫 (Type Guards)
类型守卫是能够在特定作用域中确定变量类型的表达式。
1. typeof 类型守卫
function printValue(value: string | number) {if (typeof value === "string") {// 在这个作用域中,value 被识别为 string 类型console.log(value.toUpperCase());} else {// 在这个作用域中,value 被识别为 number 类型console.log(value.toFixed(2));}
}
2. instanceof 类型守卫
class Dog {bark() {console.log("Woof!");}
}class Cat {meow() {console.log("Meow!");}
}function handleAnimal(animal: Dog | Cat) {if (animal instanceof Dog) {animal.bark(); // 正确:animal 被识别为 Dog 类型} else {animal.meow(); // 正确:animal 被识别为 Cat 类型}
}
3. in 操作符类型守卫
interface Circle {kind: "circle";radius: number;
}interface Square {kind: "square";sideLength: number;
}function getArea(shape: Circle | Square) {if ("radius" in shape) {// shape 被识别为 Circle 类型return Math.PI * shape.radius ** 2;} else {// shape 被识别为 Square 类型return shape.sideLength ** 2;}
}
4. 自定义类型守卫
function isString(value: any): value is string {return typeof value === "string";
}function isNumber(value: any): value is number {return typeof value === "number" && !isNaN(value);
}function processValue(value: string | number) {if (isString(value)) {console.log("String length:", value.length);} else if (isNumber(value)) {console.log("Number squared:", value * value);}
}
可辨识联合 (Discriminated Unions)
可辨识联合是一种通过共享字面量字段来区分联合类型成员的模式。
基本概念
// 定义可辨识联合
type Shape = | { kind: "circle"; radius: number }| { kind: "square"; sideLength: number }| { kind: "rectangle"; width: number; height: number };// 使用可辨识联合
function getArea(shape: Shape): number {switch (shape.kind) {case "circle":// TypeScript 知道 shape 是 Circle 类型return Math.PI * shape.radius ** 2;case "square":// TypeScript 知道 shape 是 Square 类型return shape.sideLength ** 2;case "rectangle":// TypeScript 知道 shape 是 Rectangle 类型return shape.width * shape.height;default:// 穷尽性检查const _exhaustiveCheck: never = shape;return _exhaustiveCheck;}
}
更复杂的例子
// 网络请求状态的可辨识联合
type NetworkState =| { state: "loading" }| { state: "success"; data: string }| { state: "error"; error: Error };function handleNetworkState(networkState: NetworkState) {switch (networkState.state) {case "loading":console.log("Loading...");break;case "success":console.log("Data:", networkState.data); // 可以安全访问 databreak;case "error":console.log("Error:", networkState.error.message); // 可以安全访问 errorbreak;}
}
带函数的可辨识联合
type Action =| { type: "ADD_TODO"; payload: string }| { type: "REMOVE_TODO"; payload: number }| { type: "TOGGLE_TODO"; payload: number };function todoReducer(state: Todo[], action: Action): Todo[] {switch (action.type) {case "ADD_TODO":// action.payload 是 string 类型return [...state, { id: Date.now(), text: action.payload, completed: false }];case "REMOVE_TODO":// action.payload 是 number 类型return state.filter(todo => todo.id !== action.payload);case "TOGGLE_TODO":// action.payload 是 number 类型return state.map(todo =>todo.id === action.payload? { ...todo, completed: !todo.completed }: todo);default:return state;}
}
预知更多信息,请阅读详情二。
