# 类型保护

原文地址 (opens new window)

在本教程中,你将学习 TypeScript 中的类型保护。

使用 条件代码块 限定变量类型的范围,达到类型保护的目的。

# typeof

看看下面的例子:

type alphanumeric = string | number;

function add(a: alphanumeric, b: alphanumeric) {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }

  if (typeof a === 'string' && typeof b === 'string') {
    return a.concat(b);
  }

  throw new Error(
    'Invalid arguments. Both arguments must be either numbers or strings.',
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

它是这样工作的:

  • 首先定义了 alphanumeric 类型,它可以保存 字符串类型 或者 数字类型 的值;
  • 接下来,定义了 add() 函数,它把类型为 alphanumericab 变量的值进行相加;
  • 然后使用 typeof 操作符检查两个参数的类型是否都为 number 类型,如果是的话,使用 + 操作符计算参数值之和;
  • 再然后使用 typeof 操作符检查两个参数的类型是否都为 string 类型,如果是的话,把两个字符串参数值拼接起来;
  • 最后,如果两个参数不都是数字类型或者不都是字符串类型的话,抛出错误提示。

在这个例子中,TypeScript 知道如何在条件代码块中使用 typeof 操作符。

在下面的 if 语句中,TypeScript 认为 ab 变量都是数字类型:

if (typeof a === 'number' && typeof b === 'number') {
  return a + b;
}
1
2
3

类似地,在下面的 if 语句中,TypeScript 将 ab 变量作为字符串来处理,因此,可以把它们拼接成一个字符串:

if (typeof a === 'string' && typeof b === 'string') {
  return a.concat(b);
}
1
2
3

# instanceof

typeof 操作符类似,TypeScript 也知道如何使用 instanceof 操作符,如下所示:

class Customer {
  isCreditAllowed(): boolean {
    // ...
    return true;
  }
}

class Supplier {
  isInShortList(): boolean {
    // ...
    return true;
  }
}

type BusinessPartner = Customer | Supplier;

function signContract(partner: BusinessPartner): string {
  let message: string;
  if (partner instanceof Customer) {
    message = partner.isCreditAllowed()
      ? 'Sign a new contract with the customer'
      : 'Credit issue';
  }

  if (partner instanceof Supplier) {
    message = partner.isInShortList()
      ? 'Sign a new contract the supplier'
      : 'Need to evaluate further';
  }

  return message;
}
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

它这样何工作的:

  • 首先,声明了 CustomerSupplier 两个类;
  • 第二, 创建类型别名为 BusinessPartner 的类型,它是CustomerSupplier 的联合类型;
  • 第三,定义 signContract() 函数,它接受一个类型为 BusinessPartner 的参数;
  • 最后,检查 partner 是否为 Customer 或者 Supplier 类的实例,然后进行对应的逻辑处理。

在下面的 if 代码块中,TypeScript 通过 instanceof 操作符知道 partnerCustomer 类型的一个实例:

if (partner instanceof Customer) {
  message = partner.isCreditAllowed()
    ? 'Sign a new contract with the customer'
    : 'Credit issue';
}
1
2
3
4
5

同样的方式,在下面的 if 代码块中,TypeScript 知道 partnerSupplier 类型的一个实例:

if (partner instanceof Supplier) {
  message = partner.isInShortList()
    ? 'Sign a new contract with the supplier'
    : 'Need to evaluate further';
}
1
2
3
4
5

if 语句限定了一种类型,TypeScript 知道在 else 语句中会是另外一种类型,如下所示:

function signContract(partner: BusinessPartner): string {
  let message: string;
  if (partner instanceof Customer) {
    message = partner.isCreditAllowed()
      ? 'Sign a new contract with the customer'
      : 'Credit issue';
  } else {
    // must be Supplier
    message = partner.isInShortList()
      ? 'Sign a new contract with the supplier'
      : 'Need to evaluate further';
  }
  return message;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# in

in 操作符通过判断对象上是否存在某个属性来进行安全检查,也可以将它用作类型保护,如下所示:

function signContract(partner: BusinessPartner): string {
  let message: string;
  if ('isCreditAllowed' in partner) {
    message = partner.isCreditAllowed()
      ? 'Sign a new contract with the customer'
      : 'Credit issue';
  } else {
    // must be Supplier
    message = partner.isInShortList()
      ? 'Sign a new contract the supplier '
      : 'Need to evaluate further';
  }
  return message;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 用户自定义的类型保护

用户自定义的类型保护允许你使用函数的时候定义类型保护或者帮助 TypeScript 推断类型。用户自定义的类型保护函数是一个返回 arg is aType 判断的函数,如下所示:

function isCustomer(partner: any): partner is Customer {
  return partner instanceof Customer;
}
1
2
3

在这个例子中,isCustomer() 是一个用户自定义的类型保护函数,可以按照下面的例子来使用它:

function signContract(partner: BusinessPartner): string {
  let message: string;
  if (isCustomer(partner)) {
    message = partner.isCreditAllowed()
      ? 'Sign a new contract with the customer'
      : 'Credit issue';
  } else {
    message = partner.isInShortList()
      ? 'Sign a new contract with the supplier'
      : 'Need to evaluate further';
  }

  return message;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 小结

  • 类型保护限定了条件语句中变量的类型;
  • 使用 typeofinstanceof 操作符在条件语句中实现类型保护。