// 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
type IntersectParameters<l extends readonly unknown[], r extends readonly unknown[]> =
[VariadicType<l>, VariadicType<r>] extends [never, never]
? IntersectStaticParameters<l, r>
: [...IntersectStaticParameters<l, r>, ...CombineTypes<[VariadicType<l>, VariadicType<r>]>[]]
type IntersectStaticParameters<
l extends readonly unknown[],
r extends readonly unknown[],
Static extends any[] = [],
I extends string = `${Static['length']}`,
> =
I extends keyof l | keyof r
? [IsFinalElementOptional<I, l, Static>, IsFinalElementOptional<I, r, Static>] extends [true, true]
? [CombineParameterTypes<l, r, I>?, ...IntersectStaticParameters<l, r, [...Static, any]>]
: [CombineParameterTypes<l, r, I>, ...IntersectStaticParameters<l, r, [...Static, any]>]
: []
type IsFinalElementOptional<I, T extends readonly unknown[], Lead extends any[], TrueValue = true> =
I extends keyof T
? T extends [...Lead, any, ...any[]]
? false
: TrueValue
: true
type CombineParameterTypes<L extends readonly unknown[], R extends readonly unknown[], K extends keyof L | keyof R> =
K extends keyof L & keyof R
? CombineTypes<[L[K], R[K]]>
: K extends keyof L
? CombineTypes<[L[K], VariadicType<R>]>
: K extends keyof R
? CombineTypes<[R[K], VariadicType<L>]>
: CombineTypes<[VariadicType<L>, VariadicType<R>]>
type CombineTypes<ToMerge extends unknown[], Merged = never> =
ToMerge extends [infer First, ...infer Rest extends unknown[]]
? [Merged] extends [never]
? CombineTypes<Rest, First>
: (Merged & First) extends infer Next
? [Next] extends [never]
? CombineTypes<Rest, Merged>
: Next extends Record<PropertyKey, unknown>
? CombineTypes<Rest, {[K in keyof Next]: Next[K]}>
: CombineTypes<Rest, Next>
: never // infer Next
: Merged
type VariadicType<
T extends readonly unknown[],
Static extends any[] = [],
I extends number = Static['length']
> =
`${I}` extends keyof T
? VariadicType<T, [...Static, any?]>
: T extends [...Static, ...infer Rest extends any[]]
? Rest[number]
: never // infer Rest
Copied from alexandroppolus solution https://github.com/type-challenges/type-challenges/issues/33210
type Intr<A, B> = [A, B] extends [object, object] ? {[K in keyof (A & B)]: (A & B)[K]} : A & B;
type IntersectParameters<X extends unknown[], Y extends unknown[], R extends unknown[] = []> =
X extends []
? [...R, ...Y]
: Y extends []
? [...R, ...X]
: [X, Y] extends [[(infer FirstX)?, ...infer RestX extends unknown[]], [(infer FirstY)?, ...infer RestY extends unknown[]]]
? '0' extends (keyof X) | (keyof Y)
? [[], []] extends [X, Y]
? IntersectParameters<RestX, RestY, [...R, Intr<FirstX, FirstY>?]>
: IntersectParameters<RestX, RestY, [...R, Intr<FirstX, FirstY>]>
: [...R, ...Intr<FirstX, FirstY>[]]
: never // infer FirstX, infer RestX, infer FirstY, infer RestY
// Test cases for each parts
type _S = {
Emp: [];
Tpl: [1];
Arr: 2[];
Opt: [3?];
ArrInTpl: [...2[]];
OptArr: [3?, ...2[]];
TplOptArr: [1, 3?, ...2[]];
TplArr: [1, ...2[]];
}
type _Test1 = Expect<Equal<{
Emp: "✅";
Tpl: "❌";
Arr: "❌";
Opt: "❌";
ArrInTpl: "❌";
OptArr: "❌";
TplOptArr: "❌";
TplArr: "❌";
}, {[I in keyof _S]: _S[I] extends [] ? '✅' : '❌'}>>
type _Test2 = Expect<Equal<{
Emp: "❌";
Tpl: "✅";
Arr: "❌";
Opt: "✅";
ArrInTpl: "❌";
OptArr: "✅";
TplOptArr: "✅";
TplArr: "✅";
}, {[I in keyof _S]: '0' extends keyof _S[I] ? '✅' : '❌'}>>
type _Test3 = Expect<Equal<{
Emp: "❌";
Tpl: "✅";
Arr: "❌";
Opt: "✅";
ArrInTpl: "❌";
OptArr: "✅";
TplOptArr: "✅";
TplArr: "✅";
}, {[I in keyof _S]: '0' extends keyof _S[I] ? '✅' : '❌'}>>
type _Test4 = Expect<Equal<{
Emp: "❌";
Tpl: "✅";
Arr: "❌";
Opt: "✅";
ArrInTpl: "❌";
OptArr: "✅";
TplOptArr: "✅";
TplArr: "✅";
}, {[I in keyof _S]: '0' extends keyof _S[I] ? '✅' : '❌'}>>
type _Test5 = Expect<Equal<never, Intr<1, 2>>>
type _Test5a = Expect<Equal<{a: 1, b: 2}, Intr<{a: 1}, {b: 2}>>>
type _Test5b = Expect<Equal<'a', Intr<string, 'a'>>>
Solution by teamchong #33163