1. 联合类型

# 1. 联合类型

联合类型通常与 nullundefined 一起使用:

const sayHello = (name: string | undefined) => {
  /* ... */
};

1
2
3
4

例如,这里 name 的类型是 string | undefined 意味着可以将 stringundefined 的值传递给sayHello 函数。

sayHello("semlinker");
sayHello(undefined);

1
2
3

通过这个示例,你可以凭直觉知道类型 A 和类型 B 联合后的类型是同时接受 A 和 B 值的类型。此外,对于联合类型来说,你可能会遇到以下的用法:

let num: 1 | 2 = 1;
type EventNames = 'click' | 'scroll' | 'mousemove';

1
2
3

以上示例中的 12'click' 被称为字面量类型,用来约束取值只能是某几个值中的一个。

# 2. 可辨识联合

TypeScript 可辨识联合(Discriminated Unions)类型,也称为代数数据类型或标签联合类型。它包含 3 个要点:可辨识、联合类型和类型守卫。

这种类型的本质是结合联合类型和字面量类型的一种类型保护方法。如果一个类型是多个类型的联合类型,且多个类型含有一个公共属性,那么就可以利用这个公共属性,来创建不同的类型保护区块。

# 1.可辨识

可辨识要求联合类型中的每个元素都含有一个单例类型属性,比如:

enum CarTransmission {
  Automatic = 200,
  Manual = 300
}

interface Motorcycle {
  vType: "motorcycle"; // discriminant
  make: number; // year
}

interface Car {
  vType: "car"; // discriminant
  transmission: CarTransmission
}

interface Truck {
  vType: "truck"; // discriminant
  capacity: number; // in tons
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在上述代码中,我们分别定义了 MotorcycleCarTruck 三个接口,在这些接口中都包含一个 vType 属性,该属性被称为可辨识的属性,而其它的属性只跟特性的接口相关。

# 2.联合类型

基于前面定义了三个接口,我们可以创建一个 Vehicle 联合类型:

type Vehicle = Motorcycle | Car | Truck;

1
2

现在我们就可以开始使用 Vehicle 联合类型,对于 Vehicle 类型的变量,它可以表示不同类型的车辆。

# 3.类型守卫

下面我们来定义一个 evaluatePrice 方法,该方法用于根据车辆的类型、容量和评估因子来计算价格,具体实现如下:

const EVALUATION_FACTOR = Math.PI; 

function evaluatePrice(vehicle: Vehicle) {
  return vehicle.capacity * EVALUATION_FACTOR;
}

const myTruck: Truck = { vType: "truck", capacity: 9.5 };
evaluatePrice(myTruck);

1
2
3
4
5
6
7
8
9

对于以上代码,TypeScript 编译器将会提示以下错误信息:

Property 'capacity' does not exist on type 'Vehicle'.
Property 'capacity' does not exist on type 'Motorcycle'.

1
2
3

原因是在 Motorcycle 接口中,并不存在 capacity 属性,而对于 Car 接口来说,它也不存在 capacity 属性。那么,现在我们应该如何解决以上问题呢?这时,我们可以使用类型守卫。下面我们来重构一下前面定义的 evaluatePrice 方法,重构后的代码如下:

function evaluatePrice(vehicle: Vehicle) {
  switch(vehicle.vType) {
    case "car":
      return vehicle.transmission * EVALUATION_FACTOR;
    case "truck":
      return vehicle.capacity * EVALUATION_FACTOR;
    case "motorcycle":
      return vehicle.make * EVALUATION_FACTOR;
  }
}

1
2
3
4
5
6
7
8
9
10
11

在以上代码中,我们使用 switchcase 运算符来实现类型守卫,从而确保在 evaluatePrice 方法中,我们可以安全地访问 vehicle 对象中的所包含的属性,来正确的计算该车辆类型所对应的价格。

# 3. 类型别名

类型别名用来给一个类型起个新名字。

type Message = string | string[];

let greet = (message: Message) => {
  // ...
};
1
2
3
4
5
最后更新于: 2022/3/25 07:58:56
강남역 4번 출구
Plastic / Fallin` Dild