如何合并TypeScript联合类型?实现指定类型结构需求
解决方案:将对象联合类型转换为合并后的类型
基础场景:合并共享属性为联合类型
你定义的两个类型:
type a = { a: "hi", b: number } type b = { a: "bye", b: number }
想要得到合并后的类型{ a: "hi" | "bye", b: number },使用UnionToIntersection会得到never是因为交叉类型会将互斥的字面量属性合并为never:"hi" & "bye"本身就是不可能的类型,最终整个交叉类型变为never,这不符合你的需求。
可以使用以下工具类型实现目标:
type MergeUnion<T> = { [K in keyof T]: T[K] } // 测试 type c = MergeUnion<a | b> // 推导结果:{ a: "hi" | "bye"; b: number; }
这个类型的逻辑是:遍历联合类型的所有公共键,每个键的类型取联合中所有成员对应键的类型的联合,自动将共享属性的不同值合并为联合类型,相同类型的属性保持不变。
补充场景:合并联合类型为含可选独有属性的类型
对于以下联合类型:
type o = { type: "bar"; foo: string; bar: number; } | { type: "baz"; foo: string; baz: boolean; }
想要转换为包含必选共享属性、可选独有属性的类型,可以使用更复杂的工具类型:
// 提取联合类型的所有键 type AllKeys<T> = T extends unknown ? keyof T : never; // 合并联合类型,共享属性必选,独有属性可选 type MergeUnionWithOptional<T> = { // 处理所有联合成员共享的必选属性 [K in keyof T]: T[K] } & { // 处理仅部分成员拥有的可选属性 [K in Exclude<AllKeys<T>, keyof T>]?: T extends Record<K, infer V> ? V : never } extends infer Merged ? { [K in keyof Merged]: Merged[K] } : never; // 测试 type MergedO = MergeUnionWithOptional<o>; // 推导结果:{ // type: "bar" | "baz"; // foo: string; // bar?: number; // baz?: boolean; // }
逻辑说明:
AllKeys<T>:遍历联合类型的每个成员,收集所有可能的键,得到所有键的联合集合;- 第一部分
[K in keyof T]:筛选出所有联合成员都包含的键,作为必选属性,类型为对应键在联合中的类型联合; - 第二部分
Exclude<AllKeys<T>, keyof T>:筛选出仅部分成员拥有的键,标记为可选属性,类型为对应键在包含它的成员中的类型; - 最后交叉两部分并展开,得到结构清晰的合并类型。
内容的提问来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

