联合类型

在TypeScript中,一个变量不会被限制为单一的类型,如果你希望一个变量的值,可以有多种类型,那么就可以使用TypeScript提供的联合类型(Union Type)。如下的示例,联合类型可以是联合基本类型,也可以是联合复杂类型:

  1. let stringOrBoolean: string | boolean = 'typescript';
  2. interface Cat {
  3. weight: number;
  4. }
  5. interface Lion {
  6. name: string;
  7. }
  8. let animal: Cat | Lion;

联合有什么用呢?通常来说都是用于函数的入参、返回值,让一个函数可以接受不同的参数/返回不同类型的返回值。
当我们使用联合类型时,我们必须尽量把当前值的类型收窄(narrowing type)为实际类型,而类型保护(type guard)就是实现类型收窄的一种手段。

类型保护

根据TypeScript官方文档描述:

A type guard is some expression that performs a runtime check that guarantees the type in some scope.

类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值。目前主要有以下方式来实现类型保护:

in 关键字

in 操作符可以安全的检查一个对象上是否存在一个属性,当一个联合类型是object型,且存在可以区分的不同字段,例如下面的两个类型,蔬菜和肉类都有name字段,但是有各自不同的其他字段,当一个类型是这两者联合时,可以通过in关键字去收窄类型:

  1. interface Vegetable {
  2. name: string;
  3. /** 含水量 */
  4. waterContent: number;
  5. }
  6. interface Meat {
  7. name: string;
  8. /** 蛋白质含量 */
  9. proteinContent: number;
  10. }
  11. type Food = Vegetable | Meat;
  12. function printFoodInformation(food: Food) {
  13. console.log('名称: ' + food.name);
  14. if ('waterContent' in food) {
  15. console.log('蔬菜含水量: ' + food.waterContent);
  16. } else if ('proteinContent' in food) {
  17. console.log('肉类蛋白质含量: ' + food.proteinContent);
  18. }
  19. }

typeof 关键字

以下几个字符串可以与typeof运算比较

  • "string"
  • "number"
  • "bigint"
  • "boolean"
  • "symbol"
  • "undefined"
  • "object"
  • "function"