我正在查看标准库中包含的一些较酷的类型函数,因此开始玩游戏。这样在TypeScript中实际上有可能吗?
interface OriginalType {
A: { a : string }
B: { b1 : string, b2: number }
C: {}
D: {c: string}
}
const r : {a: string, b1: string, b2: string} = pickAndFlatten<OriginalType>(['A', 'B'])
答案 0 :(得分:5)
我们可以通过创建所选属性类型的交集来做到这一点。
type UnionToIntersection<U> = (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type PickAndFlatten<T, K extends keyof T> = UnionToIntersection<T[K]>
UnionToIntersection
由@jcalz here提供,您应该在那里看到说明(不要忘了感谢他:)。 T[K]
将为我们提供密钥K
的类型。如果K
是键的联合,则T[K]
将是联合中所有属性类型的联合。
要在函数中使用此参数,我们将需要两个类型参数,一个代表我们选择的类型,一个代表我们选择的键。
interface OriginalType {
A: { a : string }
B: { b1 : string, b2: number }
C: {}
D: {c: string}
}
type UnionToIntersection<U> = (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type PickAndFlatten<T, K extends keyof T> = UnionToIntersection<T[K]>
function pickAndFlatten<T, K extends keyof T>(o: T, keys : K[]) :PickAndFlatten<T, K> {
// Untested implemenattion
let entries = Object.entries(o)
.filter(([k,v]) => keys.includes(k as K))
.map(([k,v]) => v);
return Object.assign({}, entries) as any;
}
let o : OriginalType;
const r = pickAndFlatten(o, ['A', 'B']) // {a: string;} & {b1: string;b2: number;}