TypeScript 如何实现可提取多个嵌套属性子键的PickMultiple工具类型
实现代码
首先需要先实现一个通用的联合转交叉工具类型,再基于它实现PickMultiple:
// 通用工具类型:将联合类型转换为交叉类型 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never // 目标PickMultiple实现 type PickMultiple<T, KArr extends Array<keyof T>> = UnionToIntersection<T[KArr[number]]>
实现逻辑说明
- 泛型约束
KArr extends Array<keyof T>:保证传入的数组元素只能是目标接口的顶级键,避免传入非法键 KArr[number]:将数组类型转换为数组元素组成的联合类型,比如['a','b']会被转换为'a' | 'b'T[KArr[number]]:拿到所有选中顶级键对应的子对象的联合类型,示例中得到{name: string} | {age: number}UnionToIntersection:将联合类型转换为交叉类型,示例中最终得到{name: string} & {age: number},也就是符合要求的平层类型
效果验证
代入你提供的示例代码测试完全符合预期:
interface A{ a:{ name: string } b:{ age: number } } const child: PickMultiple<A, ['a','b']> = { name: 'mike', age: 18 } // 类型校验正常通过,无报错
可选简化写法(无同名属性场景可用)
如果你的使用场景里不存在多个子对象有同名属性的情况,可以不用额外引入UnionToIntersection,用映射类型直接实现:
type PickMultiple<T, KArr extends Array<keyof T>> = { [K in keyof T[KArr[number]]]: T[KArr[number]][K] }
两种实现的差异在于:如果出现同名属性,交叉类型版本会取属性类型的交集,映射类型版本会取属性类型的联合,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者xipper
相关产品推荐
相关产品推荐

