2

Say there's a function X which takes any number of objects:

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

I would like it to return the intersection of every object in that list. For instance, given objects A, B, C and D it would go something like:

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

However, I would like to do this as a type for the return type of the function (hence MergedClasses)

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

I know it's possible to do [K for keyof C]: but from there I'm not sure how I could combine the objects, since there is no way to assign variables.

I checked out Lodash's merge typings and it is just an overloaded function that takes 1, 2, 3, 4 or 5 objects. So it seems like it can merge any number of objects, but it can't actually do more than 5.

Is it possible to dynamically merge the objects, or will I have to take the same route as Lodash did?

1
  • Each parameter needs an explicit generic type, so you'll need to go with the Lodash route Commented May 10, 2021 at 17:53

1 Answer 1

5

Here's a solution using a recursive definition:

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

Here's an alternative, slightly messier solution using the UnionToIntersection helper from this answer, which might be preferable if the first solution runs up against the compiler's recursion limit. However, note that this will have incorrect behaviour if any of the input types is a union, since those will be converted to intersections too.

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.