一、简介
TypeScript中的类型守卫(Type Guards)是一种技术,它可以用于在代码中更明确地指定变量的类型。这是TypeScript提供的一种强大功能,因为它可以帮助开发者避免类型错误,同时还能利用TypeScript的类型系统来提供更好的代码智能提示和自动补全。类型守卫主要用于告诉TypeScript编译器,某个变量在特定的代码块中是特定的类型。
二、使用场景
类型守卫一般要配合if语句
,在if语句
创建的块级作用域中收窄对应变量的类型。当然也可以使用三目运算符、逻辑与运算符等使用。
1. 区分联合类型
typescript
function process(input: string | number) {
if (typeof input === "string") {
// do something...
} else {
// do something...
}
}
2. 收窄类型
typescript
function move(animal: Animal) {
if (animal instanceof Bird) {
animal.fly();
} else if (animal instanceof Fish) {
animal.swim();
} else {
// do something...
}
}
3. 处理未知类型
typescript
function move(animal: unknown) {
// do something...
}
三、写法
1. "instanceof " 操作符
当你想要检查一个对象是否是某个类的实例时,可以使用instanceof
。
typescript
abstract class Animal {
abstract makeSound(): void;
}
abstract class Fish extends Animal {
abstract swim(): void;
}
abstract class Bird extends Animal {
abstract fly(): void;
}
class Shark extends Fish {
makeSound() {
console.log("Shark make sound");
}
swim() {
console.log("Shark swim");
}
}
class Eagle extends Bird {
makeSound() {
console.log("Eagle make sound");
}
fly() {
console.log("Eagle fly");
}
}
function getMovement(animal: Animal) {
if (animal instanceof Fish) {
// 在这个作用域(if创建的作用域)中,animal 被收窄为 Fish
return animal.swim();
}
if (animal instanceof Bird) {
// 在这个作用域(if创建的作用域)中,animal 被收窄为 Bird
return animal.fly();
}
}
2. "in" 操作符
这种方式主要用于检查一个具有特定属性的对象。
typescript
abstract class Animal {
abstract makeSound(): void;
}
abstract class Fish extends Animal {
abstract swim(): void;
}
abstract class Bird extends Animal {
abstract fly(): void;
}
class Shark extends Fish {
makeSound() {
console.log("Shark make sound");
}
swim() {
console.log("Shark swim");
}
}
class Eagle extends Bird {
makeSound() {
console.log("Eagle make sound");
}
fly() {
console.log("Eagle fly");
}
}
function getMovement2(animal: Animal) {
if ("swim" in animal) {
return animal.swim();
}
if ("fly" in animal) {
return animal.fly();
}
}
3. 自定义类型守卫
在复杂的应用中,可能需要基于特定逻辑来确定变量的类型,此时可以创建自定义的类型守卫。通过类型谓词"is" 实现变量类型的收窄。
typescript
abstract class Animal {
abstract makeSound(): void;
}
abstract class Fish extends Animal {
abstract swim(): void;
}
abstract class Bird extends Animal {
abstract fly(): void;
}
class Shark extends Fish {
makeSound() {
console.log("Shark make sound");
}
swim() {
console.log("Shark swim");
}
}
class Eagle extends Bird {
makeSound() {
console.log("Eagle make sound");
}
fly() {
console.log("Eagle fly");
}
}
function isAccurateAnimal<T extends Animal>(
animal: unknown,
type: abstract new (...args: any[]) => T
): animal is T {
return animal instanceof type;
}
function getMovement(animal: Animal) {
if (isAccurateAnimal(animal, Fish)) {
animal.swim();
}
if (isAccurateAnimal(animal, Bird)) {
animal.fly();
}
}
自定义类型守卫传入需要收窄类型的变量,并定义相应的收窄类型,返回布尔值的结果,当结果为真则变量的类型收窄为定义的类型,反之不进行收窄。
typescript
function narrowType(object: unknown): object is [NarrowedType] {
return [condition]
}