如何实现 TypeScript 的类型守卫?
描述 TypeScript 中实现类型守卫的几种方法及其应用场景。
类型守卫(Type Guards)是 TypeScript 中的一种机制,用于在运行时检查变量类型以缩小其类型范围,从而提升类型安全性和代码智能提示功能。以下是实现类型守卫的几种主要方法:
- 使用
typeof
守卫(检查基础类型)
适用于判断变量是否属于 JavaScript 内置基础类型(如 string、number)。function padLeft(value: string, padding: string | number) { if (typeof padding === "number") { return " ".repeat(padding) + value; // padding 被缩小为 number } if (typeof padding === "string") { return padding + value; // padding 被缩小为 string } throw new Error("期望输入是 number 或 string 类型"); }
- 使用
instanceof
守卫(检查类实例类型)
用于验证对象是否属于特定类的实例,常在类继承体系中应用。class Animal {} class Dog extends Animal { bark() {} } class Cat extends Animal { meow() {} } function makeSound(pet: Animal) { if (pet instanceof Dog) { pet.bark(); // pet 被缩小为 Dog } else if (pet instanceof Cat) { pet.meow(); // pet 被缩小为 Cat } }
- 使用
in
操作符守卫(检查对象属性)
通过检查属性存续性来区分对象类型,特别适合接口类型联合的场景。interface Cat { meow: () => void; } interface Dog { bark: () => void; } function animalNoise(animal: Cat | Dog) { if ("meow" in animal) { animal.meow(); // animal 被缩小为 Cat } else { animal.bark(); // animal 被缩小为 Dog } }
- 使用可辨识联合类型(基于判别器属性)
需为联合类型成员定义一个共同的字面量属性(如kind
),然后用控制流语法(switch
)守卫类型。type Shape = | { kind: "circle"; radius: number } | { kind: "square"; size: number }; function getArea(shape: Shape) { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; // shape 被缩小为圆 case "square": return shape.size ** 2; // shape 被缩小为方 } }
- 使用用户定义类型守卫(自定义逻辑)
创建自定义函数,返回parameter is Type
的类型谓词表达式以执行复杂检查。interface Fish { swim: () => void; } interface Bird { fly: () => void; } function isFish(pet: Fish | Bird): pet is Fish { // 守卫表达式 return (pet as Fish).swim !== undefined; } function handlePet(pet: Fish | Bird) { if (isFish(pet)) { pet.swim(); // pet 被缩小为 Fish } else { pet.fly(); // pet 被缩小为 Bird } }