Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript generic depends on order of parameters, while it should not

I have generic mergeArrays which does not depend on order of parameters.
But when used inside another generic it seems result depend. But it is not understandable.

type Fn = (...args: any[]) => any;

type arr1LessThanOrEqual<
  T1 extends ReadonlyArray<any>,
  T2 extends ReadonlyArray<any>
  > = T1["length"] extends T2["length"]
  ? true
  : T2["length"] extends 0
  ? false
  : T2 extends [infer First, ...infer Rest]
  ? Rest extends ReadonlyArray<any>
  ? arr1LessThanOrEqual<T1, Rest>
  : never
  : never;

type mergeArrWithLeft<
  T1 extends ReadonlyArray<any>,
  T2 extends ReadonlyArray<any>
  > = readonly [
    ...{
      readonly [Index in keyof T1]: Index extends keyof T2
      ? (T1[Index] & T2[Index])
      : T1[Index];
    }
  ];

type mergeArrays<
  T1 extends ReadonlyArray<any>,
  T2 extends ReadonlyArray<any>
  > = arr1LessThanOrEqual<T1, T2> extends true
  ? mergeArrWithLeft<T2, T1>
  : mergeArrWithLeft<T1, T2>;

and here i use this generic:

type LargestArgumentsList<T extends ReadonlyArray<any>> = T extends readonly [
  (...args: infer Args) => any,
  ...infer Rest
] ?
  mergeArrays<LargestArgumentsList<Rest>, Args> // here if I swap it does not work, but generic mergeArrays does not depend on order of params, so  it is a  mistery
  : readonly [];

and it works.
but if i swap it to:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

type LargestArgumentsList<T extends ReadonlyArray<any>> = T extends readonly [
  (...args: infer Args) => any,
  ...infer Rest
] ?
  mergeArrays<Args, LargestArgumentsList<Rest>>
  : readonly [];

the behaviour of LargestArgumentsList is different, here is playground

I tried to create a generic which finds the longest list of arguments in array of function.
And i expect mergeArrays generic to not depend on order of parameters. I tested and it does not depend on order of parameters. But inside another generic(LargestArgumentsList) it works differently.

>Solution :

The definition of arr1LessThanOrEqual is missing a readonly in the T2 extends [infer First, ...infer Rest] constraint. Since Args is not readonly, arr1LessThanOrEqual works when Args is the second parameter, but if you swap it with the readonly LargestArgumentsList<Rest>, it will fail.

If you replace the constraint with

T2 extends readonly [infer First, ...infer Rest]

LargestArgumentsList will work even when the parameters are swapped.

TypeScript playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading