联合类型,交叉类型 -- Typescript基础篇(7)

276 阅读2分钟

联合类型

如果我们希望变量具有多种类型,如变量可以是number也可以是string,则可用联合类型实现。各个类型之间用|分隔:

let val: number | string;
val = 1;
val = "string";

此时的val就是一个联合类型的变量,为它赋值数值或者字符串都合法。

联合类型不仅可以是多种类型中的一个,它可以同时包括所有的类型:

interface Cat {
  name: string;
  purrs: boolean;
}
interface Dog {
  name: string;
  barks: boolean;
}

let animal: Cat | Dog = {
  name: "Bonkers",
  purrs: true,
};

animal = {
  name: "Domino",
  barks: true,
};

animal = {
  name: "Domino",
  purrs: true,
  barks: true,
};

并且在未确定变量到底是联合类型中哪一个具体类型时,只能访问联合类型各个成员都具有的公共属性:

interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

function getPet(): any {}

let pet: Bird | Fish = getPet();
pet.layEggs();

// 直接访问swim方法将会报错,必须提前确定具体类型
// pet.swim();

至于怎么确定具体的类型,类型保护章节对此有更详细的说明。

交叉类型

如果我们希望将多个类型组合在一起,如变量的类型是多个接口的组合,则可用交叉类型实现,各个类型之间用&分割:

interface Human {
  name: string;
  lifetime: number;
}

interface Identifier {
  id: number;
}

const p: Human & Identifier = {
  id: 1,
  name: "xxx",
  lifetime: 100,
};

举一个更复杂的例子,将两个对象mixin:

// 如果First或者Second没有可索引属性,在获取 a[key],b[key] 值时会报错
interface IdentifierProps {
  [key: string]: any;
}

interface First extends IdentifierProps {
  name: string;
  say: () => void;
}

interface Second extends IdentifierProps {
  run: () => void;
}

function extend(a: First, b: Second): First & Second {
  const result = {} as First & Second;

  for (const key in a) {
    if (a.hasOwnProperty(key)) {
      result[key] = a[key];
    }
  }

  for (const key in b) {
    if (b.hasOwnProperty(key)) {
      result[key] = b[key];
    }
  }

  return result;
}

const a: First = {
  name: "first",
  say() {
    console.log(`he's ${this.name}`);
  },
};

const b: Second = {
  run() {
    console.log(`${this.name} is running`);
  },
};

const mixin = extend(a, b);

mixin.say();
mixin.run();

多个对象使用交叉类型时,得到的结果是它们所有属性的组合。但多个基础类型使用交叉类型时,得到结果是各个类型的交集:

type Type1 = string | number;
type Type2 = string | boolean;

type Type3 = Type1 & Type2; // Type3为string

不管是联合类型还是交叉类型,都可使用类型别名为它重新命名为新类型:

type Animal = Bird | Fish;
type Mixin = First & Second;