这边笔记主要介绍TS的联合类型Union Types和交叉类型Intersection Types.(交叉类型的官网链接没找到😭),从下面4点介绍
- 联合类型的定义、语法
- 交叉类型的定义、语法
- 联合类型和交叉类型的异同
- 联合类型和交叉类型的命名缘由
联合类型 Union Types
先看下官网描述联合类型Union Types
A union type is a type formed from two or more other types, representing values that may be any one of those types. We refer to each of these types as the union’s members.
大概翻译下: 联合类型是由两个或更多其他类型构成的类型,表示可以是这些类型中的任意一个的值,我们将这些类型称为联合的成员类型。
语法: 用|连接起来多个类型。
这个特别常见,我们看个Vue源码里的例子。
type Primitive = string | number | boolean | bigint | symbol | undefined | null
type Builtin = Primitive | Function | Date | Error | RegExp
type Primitive定义了一个原始类型,只要是JS的7个原始类型之一都可以。然后定义了一个内置类型,只要是这5个Primitive | Function | Date | Error | RegExp内置类型之一都可以
疑问: 联合类型只能取其中任何一个类型吗?
联合类型只能取其中任何一个类型吗,取所有的任何类型可不可以呢,举一个例子
type Actor = {
name: string;
awards: string[]; // 演员获取的奖项
movieType: string[]; // 演员电影风格
};
type Dancer = {
name: string;
danceStyle: string[]; // 舞者舞蹈风格
}
type ActorOrDancer = Actor | Dancer
const liangChaoWei: Actor = {
name: '梁朝伟',
awards: ['金马奖','金像奖'],
movieType: ['战争','爱情'],
}
const yiYangQianXi: ActorOrDancer = {
name: '易烊千玺',
awards: ['百花奖','金像奖'],
movieType: ['青春','校园', '战争'],
danceStyle: ['hiphop', 'choregraphy']
}
我们定义了一个演员类型和舞者类型,还有一个联合类型,是演员或者舞者。
看到代码是完全正常的,没有任何警告,说明联合类型可以是同时包含所有的成员类型, 但是我们一般用交叉类型来表示组合类型。
交叉类型 Intersection Types
交叉类型就是用多个类型来表示一个类型,用&来连接多个类型。 举个例子。
type Actor = {
name: string;
awards: string[]; // List of awards the actor has won
movieType: string[]; // Type of movies the actor is known for
};
type Dancer = {
name: string;
danceStyle: string[];
}
type ActorOrDancer = Actor | Dancer
const liangChaoWei: Actor = {
name: '梁朝伟',
awards: ['金马奖','金像奖'],
movieType: ['战争','古装'],
}
const yiYangQianXi: ActorOrDancer = {
name: '易烊千玺',
awards: ['百花奖','金像奖'],
movieType: ['青春','爱情'],
danceStyle: ['hiphop', 'choregraphy'], // Style of dance the dancer is known for
}
type Versatile = Actor & Dancer
const wangYiBo: Versatile = {
name: '王一博',
awards: ['华鼎奖','金鹰奖'],
movieType: ['悬疑','剧情'],
danceStyle: ['hiphop', 'choregraphy'], // Style of dance the dancer is known for
}
// 这个会提示缺少演员的属性
const x: Versatile = {
name: '张三',
danceStyle: ['jazz'];
}
我们定义了多才多艺类型Versatile,既有演员的才能又有舞蹈的才能
截图我们定义了一个X,只有舞者类型,就会提示缺少演员属性。看下实际代码例子,Vue源码里的h.ts文件, 渲染虚拟dom的h函数。
export function h<P>(
type: string | Component<P>,
props?: (RawProps & P) | ({} extends P ? null : never),
children?: RawChildren | RawSlots,
): VNode
我们看到props, (RawProps & P),就是既有RawProps,又有传过来的P.
联合类型和交叉类型的异同
共同点: 都是用多个类型来组成自己类型,当联合类型是表示成员里的所有类型时,它和交叉类型表示的就是完全一样的。
不同点: 交叉类型一定要成员类型的所有类型,不可以是任意一个。而联合类型可以是任意一个成员类型,也可以是所有的。
面试被问到的时候,交叉类型,当时就以为是多个类型的共同部分,现在知道了是把多个类型合并起来,那为什么要叫交叉类型呢?
联合类型和交叉类型的命名缘由
看下面这张图,来自于这篇笔记Typescript and Set Theory, 联合类型就是就是取集合成员的联合,包括集合成员本身和交集,也就是数学里面的并集,这也就是为什么联合类型取任意类型或包含的所有类型都可以,也可以理解为什么叫联合类型,就是集合的并集。
同理:交叉类型, 把组成的每个类型看成一个集合,取集合的交集,所以要同时满足所有的组成类型,而不是所有的组成类型共同部分,这样也就明白了为什么要叫交叉类型,原来和数学的集合有关。