TypeScript的几种类型保护方式

开发 前端
typeof​ 是 JavaScript 中的一个操作符,TypeScript 使用它来检查基本数据类型(如 string​, number​, boolean)。常用于保护原始类型。

TypeScript 的 类型保护(Type Guards)是一种确保在代码运行时可以更精确地处理特定类型的方法。通过类型保护,TypeScript 能够根据特定的条件(如值的属性或操作方式)推断变量的类型,从而减少类型错误的可能性。

常见的几种类型保护方式

  1. typeof 类型保护
  2. instanceof 类型保护
  3. in 操作符
  4. 自定义类型保护函数(Type Predicates)
  5. 字面量类型守护(Discriminated Unions)

1. typeof 类型保护

typeof 是 JavaScript 中的一个操作符,TypeScript 使用它来检查基本数据类型(如 string, number, boolean)。常用于保护原始类型。

示例:

function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log("The value is a string:", value.toUpperCase());
  } else {
    console.log("The value is a number:", value.toFixed(2));
  }
}

printValue("Hello"); // The value is a string: HELLO
printValue(123.456); // The value is a number: 123.46

在这个例子中,typeof 通过检查 value 是 string 还是 number 来选择合适的操作。

2. instanceof 类型保护

instanceof 检查某个对象是否是另一个对象的实例(即其构造函数的原型是否出现在该对象的原型链中)。适用于类实例的类型保护。

示例:

class Dog {
  bark() {
    console.log("Woof!");
  }
}

class Cat {
  meow() {
    console.log("Meow!");
  }
}

function makeSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark(); // Safe to call bark() here
  } else {
    animal.meow(); // Safe to call meow() here
  }
}

const myDog = new Dog();
const myCat = new Cat();

makeSound(myDog); // Woof!
makeSound(myCat); // Meow!

在这个例子中,instanceof 检查对象是否是 Dog 或 Cat 的实例,以选择调用哪个方法。

3. in 操作符

in 操作符检查对象中是否存在某个属性,这对于联合类型中可能包含不同属性的情况非常有用。

示例:

interface Car {
  drive(): void;
}

interface Boat {
  sail(): void;
}

function move(vehicle: Car | Boat) {
  if ("drive" in vehicle) {
    vehicle.drive(); // Safe to call drive() here
  } else {
    vehicle.sail(); // Safe to call sail() here
  }
}

const car: Car = {
  drive() {
    console.log("Driving the car");
  },
};

const boat: Boat = {
  sail() {
    console.log("Sailing the boat");
  },
};

move(car);  // Driving the car
move(boat); // Sailing the boat

这里,in 操作符检查 vehicle 是否有 drive 属性,以此决定执行 drive() 或 sail()。

4. 自定义类型保护函数(Type Predicates)

通过使用 类型谓词(Type Predicates),可以创建自定义的类型保护函数。类型谓词的语法是:param is Type,它表明如果函数返回 true,则 param 的类型为 Type。

示例:

interface Fish {
  swim(): void;
}

interface Bird {
  fly(): void;
}

function isFish(animal: Fish | Bird): animal is Fish {
  return (animal as Fish).swim !== undefined;
}

function moveAnimal(animal: Fish | Bird) {
  if (isFish(animal)) {
    animal.swim(); // TypeScript knows `animal` is a Fish
  } else {
    animal.fly(); // TypeScript knows `animal` is a Bird
  }
}

const fish: Fish = {
  swim() {
    console.log("The fish is swimming");
  },
};

const bird: Bird = {
  fly() {
    console.log("The bird is flying");
  },
};

moveAnimal(fish); // The fish is swimming
moveAnimal(bird); // The bird is flying

在这个例子中,isFish 是一个自定义类型保护函数。它检查 animal 是否为 Fish,并根据类型来调用相应的方法。

5. 字面量类型守护(Discriminated Unions)

字面量类型守护是通过在联合类型中引入一个区分字段(discriminant field)来实现的。通常在每个类型中使用一个固定的字面量属性来进行类型保护。

示例:

interface Square {
  kind: "square";
  size: number;
}

interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}

interface Circle {
  kind: "circle";
  radius: number;
}

type Shape = Square | Rectangle | Circle;

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "square":
      return shape.size * shape.size;
    case "rectangle":
      return shape.width * shape.height;
    case "circle":
      return Math.PI * shape.radius * shape.radius;
    default:
      return 0;
  }
}

const square: Square = { kind: "square", size: 5 };
console.log(getArea(square)); // 25

在这个例子中,Shape 类型是由 Square, Rectangle 和 Circle 组成的联合类型,它们都有 kind 字段,通过这个字段我们可以区分出当前的具体类型并相应处理。

总结

TypeScript 提供了多种类型保护方式来安全地处理联合类型或复杂的类型结构:

  • typeof: 用于检查基本数据类型 (string, number, boolean)。
  • instanceof: 用于检查对象是否是某个类的实例。
  • in: 用于检查对象是否具有某个属性。
  • 自定义类型保护函数: 通过类型谓词创建自定义的类型保护函数。
  • 字面量类型守护(Discriminated Unions): 使用区分字段来区分联合类型中的不同类型。

这些类型保护方式可以帮助你在 TypeScript 中更安全地编写代码,并减少运行时错误。

责任编辑:武晓燕 来源: 宇宙一码平川
相关推荐

2025-01-20 00:00:00

TypeScript​​typeof​​数据

2022-06-27 09:45:22

MySQL索引

2011-12-26 15:58:01

枚举

2010-03-12 17:29:16

Python模块

2021-12-20 23:24:40

前端测试开发

2020-09-23 07:47:14

Java方式类型

2023-07-04 15:11:30

TypeScript类型保护

2022-02-25 14:06:01

区块链生态系统技术

2021-09-09 13:53:08

区块链加密货币技术

2020-12-30 07:55:37

C++转换类型

2021-03-11 14:46:05

C++类型转换语言

2022-08-31 07:04:50

Bean作用域

2022-03-11 15:40:49

PaaS云服务

2021-06-15 09:12:19

TypeScriptTypeScript Javascript

2021-05-07 16:19:36

异步编程Java线程

2022-02-25 09:06:02

TypeScripnever工具

2021-07-27 06:06:34

TypeScript语言运算符

2021-01-19 11:56:19

Python开发语言

2010-09-25 14:48:55

SQL连接

2024-03-12 08:29:28

C++类型转换方式
点赞
收藏

51CTO技术栈公众号