我正在查看标准库中包含的一些较酷的类型函数,我开始玩了.在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'])
Run Code Online (Sandbox Code Playgroud)
我们可以通过创建拾取的属性类型的交集来实现这一点.
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]>;
Run Code Online (Sandbox Code Playgroud)
UnionToIntersection由@jcalz 在这里提供,你应该在那里看到解释(不要忘记用upvote感谢他:)).T[K]会给我们钥匙的类型K.如果K是键的并集,T[K]则将是union中所有属性类型的并集.
要在函数中使用它,我们需要两个类型参数,一个表示我们从一个中选择的类型来表示我们正在挑选的键.
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 implementation
const 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; }
Run Code Online (Sandbox Code Playgroud)