// type MergeObjects<T, U> = T extends object
? U extends object
? { [K in keyof T | keyof U]: K extends keyof T
? K extends keyof U
? T[K] | U[K]
: T[K]
: K extends keyof U
? U[K]
: never }
: T
: U;
type IntersectParameters<T extends readonly any[], U extends readonly any[]> = {
[K in keyof T | keyof U]: K extends keyof T
? K extends keyof U
? T[K] extends infer A
? U[K] extends infer B
? A extends [...infer ATail]
? B extends [...infer BTail]
? [...IntersectParameters<ATail, BTail>]
: A
: B
: never
: never
: T[K]
: K extends keyof U
? U[K]
: never;
};
type Result = IntersectParameters<
[{ a: 0 }, { b: 1 }?, { c: 2 }?, ...{ d: 3 }[]],
[{ e: 4 }?, { f: 5 }?, ...{ g: 6 }[]]
>;
// Expected Result:
type Expected = [
{
a: 0;
e: 4;
},
{
b: 1;
f: 5;
}?,
{
c: 2;
g: 6;
}?,
...{
d: 3;
g: 6;
}[]
];
Solution by Swastik777YT #34918
type Arr = readonly unknown[];
type Intr<A, B> = [A, B] extends [object, object] ? {[K in keyof (A & B)]: (A & B)[K]} : A & B;
type IntersectParameters<X extends Arr, Y extends Arr, R extends Arr = []> = X extends readonly []
? [...R, ...Y]
: Y extends readonly []
? [...R, ...X]
: [X, Y] extends [readonly [(infer A)?, ...infer XT], readonly [(infer B)?, ...infer YT]]
? '0' extends (keyof X) | (keyof Y)
? IntersectParameters<XT, YT, [[], []] extends [X, Y] ? [...R, Intr<A, B>?] : [...R, Intr<A, B>]>
: [...R, ...Intr<A, B>[]]
: never;
Solution by alexandroppolus #33210
// to support tuple of any length
type IntersectParameters<l extends readonly unknown[], r extends readonly unknown[]>
= keyof r extends keyof l // make sure l is longer or equal to r
? {[I in keyof l]: number extends I ? Intersect<l[I], r[10000]>
: I extends `${infer I extends number}` ? Intersect<Required<l>[I], Required<r>[I]>
: l[I];
} extends infer Joined extends readonly unknown[]
? `${Joined[10000] extends undefined ? 0 : 1}${r[10000] extends undefined ? 0 : 1}` extends '01'
? [...Joined, ...r[10000][]] : Joined : never
: IntersectParameters<r, l>; // if r is longer, swap l with r
type Intersect<A, B> = [A & B] extends [never] ? A
: [A, B] extends [object, object] ? { [P in keyof (A & B)]: (A & B)[P] }
: B extends undefined ? A
: A extends undefined ? B
: A & B;
Solution by teamchong #33163