TS 小记(8)TypeScript 高级类型

114 阅读2分钟

联合类型(Union Types)

联合类型(Union Types)是指一个变量可以有多种类型,多个类型之间用 | 符号表示。比如 number | string 是指该变量的类型可能是 number 或者 string,这两种类型的值都可以赋值给这个变量,不是这两种类型的值则不能赋值给这个变量,否则编译报错。

let x: number | string = 1; // 可以赋值
x = "Hello";  // 可以赋值
x = true;     // 不可以赋值,报错

联合类型可以作为函数参数使用:

function printName(name: string | string[]) {
  if (typeof name === 'string') {
    console.log("Hello, " + name);
  } else {
    const names = name.join(" ");
    console.log("Hello, " + names);
  }
}

printName("Owen");
printName(["Sam", "Bob", "Tom"]);

// 运行结果
Hello, Owen
Hello, Sam Bob Tom

联合类型可以在接口中使用,接口中的可选属性,类型都是联合类型,指定的类型 | undefined

interface Person {
  birthday: number | string;  // 可以是个 number 类型或者是 string 类型
  nickname?: string;     // 可以没有昵称,是个可选属性,类型是 string | undefined 
}

如果一个变量是个联合类型,则这个变量只能访问联合类型中所有类型都共有的成员(属性或方法)。这是为了避免在运行时类型不匹配而造成运行时错误。

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

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

function getSmallPet(): Fish | Bird {
  // ...
}

let pet = getSmallPet();
pet.layEggs(); // 可以调用 layEggs 方法
pet.swim();    // 报错:类型“Fish | Bird”上不存在属性“swim”。类型“Bird”上不存在属性“swim”。

交叉类型(Intersection Types)

交叉类型是将多个类型合并成一个类型。它可以把多个类型叠加在一起组成一个新的类型,新类型包含之前多个类型中的所有成员。类型交叉使用 & 运算符表示。比如:Person & Serializable & Comparable同时是 PersonSerializableComparable,包含这三者的所有成员。

交叉类型常用于混入(mixins)或其他不适合继承的场景中。

比如 Switch 是前端开发中场景的一个 UI 组件,我们来定义一个 Switch 组件的属性:

interface SwtichConfig {
  isChecked: boolean;
  onCheckChanged?: (isChecked) => void;
}

比如一些 App 中设置页里常见到很多设置项,我们开发时可能会抽象出 Cell 这样一个 UI 组件,定义一些 Cell 组件的常用属性:

interface CellConfig {
  title: string;
  subtitle?: string;
  icon?: string;
  onClick?: () => void;
}

现在考虑一个场景,有个设置项,有 title、subtitle 等描述信息,右侧有个 Switch,可以开启或者关闭这个设置项。这时候我们需要一个 SwitchCell,这时候我们定义 SwitchCellConfig 有两种做法:

第一种是继承思想,定义一个接口 SwitchCellConfig 继承自 SwitchConfigCellConfig

interface SwitchCellConfig extends SwitchConfig, CellConfig {
  
} 

第二种方式是组合思想,使用交叉类型:

type SwitchCellConfig = SwitchConfig & CellConfig;

这里的 type 关键字是用来给 SwitchConfig & CellConfig 这个交叉类型取一个别名。

两者可以实现一致的效果,但语义上有差异。


开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情