Skip to content
On this page

联合类型

声明的类型并不确定,可以为多个类型中的一个

typescript
let a: number | string = "a";
let b: number | string = 1;
1
2

有时候不仅要限制变量的类型,还需要限定变量的取值在某个特定的范围内

字符串的字面量联合类型

typescript
//  testName是一个联合类型,并且取值必须是   'a'|'b'|'c' 中的一个
let testName: "a" | "b" | "c";
1
2

数字的字面量联合类型

typescript
let testName: 1 | 2 | 3;
1

对象的联合类型

如果对象时联合类型,在对象不确定的情况下,只能访问所有类型的公有有成员 ( 这种情况下的联合类型只能取所有成员的交集)

typescript
interface DogInterface {
  run(): void;
}

interface CatInterface {
  jump(): void;
}

// pet变量将具有两个接口类型的所有方法
let pet: DogInterface & CatInterface = {
  run() {},
  jump() {},
};

class Dog implements DogInterface {
  run() {}
  eat() {}
}

class Cat implements CatInterface {
  jump() {}
  eat() {}
}

enum Master {
  Boy,
  Girl,
}

function getPet(master: Master) {
  // 类型推断为:  (let pet: Dog | Cat)  联合类型
  let pet = master === Master.Boy ? new Dog() : new Cat();
  // 编译器提示只能调用  eat 方法
  pet.eat();
  return pet;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

可区分的联合类型

本质上是结合联合类型与字面量类型的一种类型保护方法。核心思想:一个类型如果是多个对象的联合类型,并且每个类型之间有一个公共属性,就可以凭借此公共属性,创建类型保护区块

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

interface Reactangle {
  kind: "reactangle";
  width: number;
  height: number;
}

type Shape = Square | Reactangle;

function area(s: Shape) {
  // 通过两个类型的共有属性 kind, 就可以创建类型保护区块
  switch (s.kind) {
    case "reactangle":
      return s.height * s.width;
    case "square":
      return s.size * s.size;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

上面的代码如果不升级维护是没有问题的,但是如果添加了一个新的形状后呢?

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

interface Reactangle {
  kind: "reactangle";
  width: number;
  height: number;
}

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

type Shape = Square | Reactangle | Circle;

function area(s: Shape) {
  switch (s.kind) {
    case "reactangle":
      return s.height * s.width;
    case "square":
      return s.size * s.size;
  }
}

// 打印出 undefined
console.log(area({ kind: "circle", r: 100 }));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

解决方式一

为函数指定一个明确的返回类型

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

interface Reactangle {
  kind: "reactangle";
  width: number;
  height: number;
}

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

type Shape = Square | Reactangle | Circle;
/*
函数缺少结束 return 语句,返回类型不包括 "undefined"。ts(2366)
*/
function area(s: Shape): number {
  switch (s.kind) {
    case "reactangle":
      return s.height * s.width;
    case "square":
      return s.size * s.size;
  }
}

console.log(area({ kind: "circle", r: 100 }));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

解决方式二

检查是否是 never 类型,如果是 never 类型,说明前面所有的分支都被覆盖了, 如实 s 不是 never 类型,就说明前面的分支有遗漏

typescript
interface Reactangle {
  kind: "reactangle";
  width: number;
  height: number;
}

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

type Shape = Square | Reactangle | Circle;

function area(s: Shape) {
  switch (s.kind) {
    case "reactangle":
      return s.height * s.width;
    case "square":
      return s.size * s.size;
    default:
      /*
类型“Circle”的参数不能赋给类型“never”的参数。ts(2345)
*/
      return ((e: never) => {
        throw new Error(e);
      })(s);
  }
}

console.log(area({ kind: "circle", r: 100 }));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typescript
interface Square {
  kind: "square";
  size: number;
}

interface Reactangle {
  kind: "reactangle";
  width: number;
  height: number;
}

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

type Shape = Square | Reactangle | Circle;

function area(s: Shape) {
  switch (s.kind) {
    case "reactangle":
      return s.height * s.width;
    case "square":
      return s.size * s.size;
    // 添加上遗漏的分支即可
    case "circle":
      return Math.PI * s.r ** 2;
    default:
      return ((e: never) => {
        throw new Error(e);
      })(s);
  }
}

// 打印出正确的值
console.log(area({ kind: "circle", r: 100 }));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
沪ICP备20006251号-1