打字稿泛型遍历对象数组并与它们相交

时间:2021-05-10 17:52:26

标签: typescript

假设有一个函数 X 接受任意数量的对象:

export function X<T extends object[]>(...classes: T): MergedClasses<T>;

我希望它返回该列表中每个对象的交集。 例如,给定对象 ABCD,它将类似于:

let X = A & B
X = X & C
X = X & D
// for any number of objects

但是,我想将此作为函数返回类型的类型(因此 MergedClasses

type MergedClasses<C extends object[]> = {
}

我知道可以执行 [K for keyof C]: 但从那里我不确定如何组合对象,因为无法分配变量。

我查看了 Lodash 的 merge typings,它只是一个带有 1、2、3、4 或 5 个对象的重载函数。所以它看起来可以合并任意数量的对象,但实际上不能合并超过 5 个。

是否可以动态合并对象,还是必须采用与 Lodash 相同的路线?

1 个答案:

答案 0 :(得分:2)

这是使用递归定义的解决方案:

type IntersectionOf<A extends any[]> = A extends [infer T, ...infer R] ? T & IntersectionOf<R> : unknown

// type Test = {a: string} & {b: number} & {c: boolean}
type Test = IntersectionOf<[{a: string}, {b: number}, {c: boolean}]>

Playground Link

这是使用 this answer 中的 UnionToIntersection 帮助程序的另一种稍微混乱的解决方案,如果第一个解决方案遇到编译器的递归限制,则可能更可取:

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type IntersectionOf<A extends any[]> = UnionToIntersection<A[number]>

// type Test = {a: string} & {b: number} & {c: boolean}
type Test = IntersectionOf<[{a: string}, {b: number}, {c: boolean}]>

Playground Link