联合类型(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同时是 Person、Serializable 和 Comparable,包含这三者的所有成员。
交叉类型常用于混入(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 继承自 SwitchConfig 和 CellConfig。
interface SwitchCellConfig extends SwitchConfig, CellConfig {
}
第二种方式是组合思想,使用交叉类型:
type SwitchCellConfig = SwitchConfig & CellConfig;
这里的 type 关键字是用来给 SwitchConfig & CellConfig 这个交叉类型取一个别名。
两者可以实现一致的效果,但语义上有差异。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情