TypeScript 类型保护进阶教程

在本教程中,你将学习 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.',
  );
}

它是这样工作的:

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

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

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

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

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

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

它这样何工作的:

  • 首先,声明了 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';
}

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

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

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

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

用户自定义的类型保护

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

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

在这个例子中,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;
}

小结

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

教程来源于Github,感谢cody1991大佬的无私奉献,致敬!

技术教程推荐

推荐系统三十六式 -〔刑无刀〕

深入浅出gRPC -〔李林锋〕

Vue开发实战 -〔唐金州〕

分布式技术原理与算法解析 -〔聂鹏程〕

etcd实战课 -〔唐聪〕

操作系统实战45讲 -〔彭东〕

说透芯片 -〔邵巍〕

结构执行力 -〔李忠秋〕

结构沟通力 -〔李忠秋〕