TS 中的类型运算:交叉类型
交叉类型(交集)
英文全称:intersection types
1 2
| type A = string & number;
|
交叉类型一般多用于对象,而不用于简单类型
1 2 3 4 5 6
| type 有左手的人 = { left: string }
const b = { left: 'yse', right: 'yes' } const a1: 有左手的人 = b
const a2: 有左手的人 = { left: 'yse', right: 'yes' }
|
可用于接口求交集
1 2 3 4 5 6 7
| interface Colorful { color: string; } interface Circle { radius: number; } type ColorfulCircle = Colorful & Circle;
|
可用于模拟继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| type Person = { name: string; age: number; }; type User = Person & { id: number; email: string; }; const u: User = { id: 1, name: 'ClariS', age: 18, email: 'xxx@yyy.com' };
|
交叉类型的特殊情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| type Person = { name: string; age: number; id: string; }; type User = Person & { id: number; email: string; }; const u: User = { id: 1 as never, name: 'ClariS', age: 18, email: 'xxx@yyy.com', };
|
当把上面 id
的类型从一个比较大的类型,变为比较小的类型时,整个 User
的类型都为 never
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type Person = { name: string; age: number; id: 'A'; }; type User = Person & { id: 'B'; email: string; }; const u: User = { id: 1, name: 'ClariS', age: 18, email: 'xxx@yyy.com', };
type A = { kind: 'A'; name: string }; type B = { kind: 'B'; age: number } & A;
|
上面的例子中,当对象属性发生冲突时,type
只会把类型变为 never
,但类型并不报错,只在使用时报错;而 interface
会直接报错
1 2 3 4 5 6 7 8 9 10
| interface Person { name: string; age: number; id: string; } interface User extends Person { id: number; email: string; }
|
函数的交集会得到一个参数的并集
1 2 3 4 5 6 7 8 9 10 11 12
| type A = { method: (a: number) => void; }; type B = { method: (a: string) => void; } & A;
const b: B = { method(a) { a; } };
|
总结:交叉类型常用于有交集的类型 A、B,如果 A、B 无交集,可能得到 never
,也可能只是属性为 never