如何将TypeScript联合类型转换为合并类型:公共键转为联合类型、非公共键转为可选联合类型?
如何将TypeScript联合类型转换为合并类型:公共键转为联合类型、非公共键转为可选联合类型?
这个需求太贴合实际开发场景了!我之前处理第三方API返回类型时也碰到过一模一样的问题,刚好可以用TypeScript的分布式条件类型来实现你要的SomeMergeUtil工具类型。
先直接上可用的解决方案,你可以直接复制使用:
// 先提取联合类型中所有成员的键,合并成一个键联合 type KeysOfUnion<T> = T extends T ? keyof T : never; // 核心的合并工具类型 type MergeUnion<T> = { [K in KeysOfUnion<T>]: T extends { [P in K]: infer V } ? V : undefined; };
用你的例子测试一下,完全符合预期的效果:
type ThirdPartyUnion = {a: 'success', data: object} | {a: 'error', error: Error}; type MyIntersection = MergeUnion<ThirdPartyUnion>; // 最终生成的类型:{a: 'success' | 'error', data: object | undefined, error: Error | undefined}
简单拆解一下原理:
KeysOfUnion<T>:借助TypeScript的分布式条件类型特性,自动遍历联合类型的每个成员,把每个成员的键提取出来再合并成一个大的键联合。比如你的例子里,它会返回'a' | 'data' | 'error'。MergeUnion<T>:遍历所有收集到的键K,对每个键再次用分布式条件类型检查:如果联合里的成员包含这个键,就提取它的类型V;如果不包含,就返回undefined。这样公共键(比如你的a)会自动把所有成员的对应类型合并成联合,非公共键(data和error)则会变成「自身类型 + undefined」的形式。
你之前尝试的UnionToIntersection之所以达不到效果,是因为它的作用是把联合类型转成交叉类型——比如{a: 'success'} & {a: 'error'}会因为类型冲突变成{a: never},这和你要的“合并所有可能类型”的思路完全相反,所以得换这种「逐个收集键的所有可能类型」的方式。
再给你个更复杂的测试案例验证下:
type TestUnion = {x: number, y: string} | {x: boolean, z: symbol} | {w: bigint}; type TestMerge = MergeUnion<TestUnion>; // 最终生成的类型:{x: number | boolean, y: string | undefined, z: symbol | undefined, w: bigint | undefined}
内容来源于stack exchange
相关产品推荐
相关产品推荐

