我们有如下一个联合类型:
type union = { a: string } | { b: number } | { c: boolean }
如何得到最终的类型:
type obj = { a: string b: number c: boolean }
如果是用js来写,不要太简单,但是typescript没有对union的遍历能力,所以只能走其他办法,经过探索后最终得到如下解:
type GetUnionKeys<Unoin> = Unoin extends any ? { [key in keyof Unoin]: key; } extends { [key in keyof Unoin]: infer K; } ? K : never : never; type UnionToInterByKeys<Union, Keys extends string | number | symbol> = { [key in Keys]: Union extends any ? { [k in keyof Union]: k extends key ? Union[k] : never; } extends { [k in keyof Union]: infer P; } ? P : never : never; }; type UnionToInter<Unoin> = UnionToInterByKeys<Unoin, GetUnionKeys<Unoin>>;
在使用时如下:
type obj = UnionToInter<union>
这样就可以实现我们的目的。我写了两个原子范型,GetUnionKeys用于获取联合类型里面的全部key,UnionToInterByKeys是关键,用于基于前面获得的keys再得到最后的对象。
不过这个方法存在一定的风险,假如联合类型中存在相同的属性,那么可能存在不确定性,比如:
type obj = UnionToInter<{ a: string, b: number } | { b: boolean }>
我们最终就会得到:
type obj = { a: string b: number | boolean }
但是我们再开发中,常常会让后面一个覆盖前面的,我们期望得到的是:
type obj = { a: string b: boolean }
我之前在读一些博客的时候,有同学提到可以通过冲载机制得到联合类型中的最后一个元素,但是我没有找到这篇文章,如果你看到,请在下方留言给我。
赞
深奥, 我只会合并两个, 这种批量的就完全不会了.
type UnionZ = {
[k in (keyof A | keyof B)]: k extends keyof B ? B[k] : k extends keyof A ? A[k] : never;
};