31997-extreme-parameter-intersection

Back

// 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;

Playground

Solution by teamchong #33163