type a1 = { a: string } | { b: string } | { c: string }
需要转换成联合类型
type a2 = { a: string;} & { b: string;} & { c: string;}
这边有一个类型可以完成转换,但我不理解内部机制,请问 UnionToIntersection 含义
type UnionToIntersection<T> = (T extends any ? (a: T) => any : never) extends (
args: infer R
) => any
? R
: never;
通过分发机制将联合类型转换成函数类型我理解 (T extends any ? (a: T) => any : never)
后面通过 args: infer R
我就不理解了。
第一部分:
(T extends any ? (a: T) => any : never)
这里比较简单,逐步替换:
正如原题所述,这里发生了分发,分成了三个函数,而不是单独一个
(a: { a: string } | { b: string } | { c: string }) => any
第二部分:
extends (args: infer R) => any ? R : never
我们先代入第一部分的结果:
可以这么理解,我们要给这里填空:
但是看起来还是有点绕,不如我们把它换成函数调用:
这样看起来就正常多了,用大白话解释,我们需要一个
args
,用它既能调用(a: { a: string }) => any)
,又能调用((a: { b: string }) => any)
,又能调用((a: { c: string }) => any)
。那么很显然这个
args
要满足所有要求,只能是{ a: string, b: string, c: string }
。这里的术语叫逆变,参数类型是逆变的。
总之,这里用了两个比较少用的概念:1. 条件类型会分发联合类型 2. 函数参数是逆变的。分发是TS的一个设计决定,逆变也受到
--strictFunctionTypes
的控制,如果其他语言要实现类似功能,不一定也会写成这样。