类型保护

is

in 操作符 并不是 TypeScript 中新增的概念,而是 JavaScript 中已有的部分,它可以通过 key in object 的方式来判断 key 是否存在于 object 或其原型链上。既然能起到区分作用,那么 TypeScript 中自然也可以用它来保护类型。

interface Foo {
  foo: string;
  fooOnly: boolean;
  shared: number;
}

interface Bar {
  bar: string;
  barOnly: boolean;
  shared: number;
}

function handle(input: Foo | Bar) {
  if ('foo' in input) {
    input.fooOnly;
  } else {
    input.barOnly;
  }
}

foo / barfooOnly / barOnly 是各个类型独有的属性,因此可以作为可辨识属性(Discriminant Property 或 Tagged Property)。Foo 与 Bar 又因为存在这样具有区分能力的辨识属性,可以称为可辨识联合类型(Discriminated Unions 或 Tagged Unions)。虽然它们是一堆类型的联合体,但其中每一个类型都具有一个独一无二的,能让它鹤立鸡群的属性。

instanceof

同样的,instanceof 也可以用来进行类型保护。

class FooBase {}

class BarBase {}

class Foo extends FooBase {
  fooOnly() {}
}
class Bar extends BarBase {
  barOnly() {}
}

function handle(input: Foo | Bar) {
  if (input instanceof FooBase) {
    input.fooOnly();
  } else {
    input.barOnly();
  }
}