如何实现Typescript泛型,合并接口所有子属性为可选类型?
TypeScript 泛型实现多子对象属性合并解决方案
问题根因
你之前的写法失效的核心原因是:keyof 作用于联合类型时,只会返回联合所有成员共有的属性名。在你的示例中Test[keyof Test] 是{a:string,b:string,c:string} | {a:string,b:string,d:string},所以keyof Test[keyof Test]只能拿到共有属性a | b,自然会丢失c和d。
正确实现
简洁版实现(基于联合转交叉工具)
// 联合转交叉的通用工具类型 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // 目标泛型实现 type CombinedChildren<T extends Record<string, object>> = Partial<UnionToIntersection<T[keyof T]>>;
效果验证
export type Combined = CombinedChildren<Test>; // 完全符合预期输出: // { // a?: string; // b?: string; // c?: string; // d?: string; // }
实现原理
- 先通过
T[keyof T]拿到输入类型所有子对象的联合类型 - 用
UnionToIntersection把联合类型转成交叉类型,聚合所有子对象的属性 - 最后用
Partial把所有属性设为可选,即可得到预期结果
无额外工具类型的实现方案
如果不想引入UnionToIntersection,也可以用分发条件类型显式收集所有键实现,效果完全一致:
// 收集联合类型所有成员的全部键 type AllUnionKeys<U> = U extends any ? keyof U : never; type CombinedChildren<T extends Record<string, object>> = Partial<{ [K in AllUnionKeys<T[keyof T]>]: T[keyof T] extends Record<K, infer V> ? V : never }>
内容的提问来源于stack exchange,提问作者ecstrema
相关产品推荐
相关产品推荐

