Why does an intersection change when the types are reordered?
Taken from docs:
When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.
More explanation you can find here
When you made intersection of two functions - it is mean you made an overloading.
See next example:
type A = (a: number) => numbertype B = (b: string) => stringtype C = (c: any) => anydeclare var foo: A & B & Cfoo(2) // numberfoo('2') // stringfoo({}) // any
Above code is equal to:
function bar(a: string): string; function bar(a: number): number; function bar(a: any): any; function bar(a: number | string | any) { return null as any } bar(2); // number bar('2') // string bar({}) // any
Please keep in mind, that I put less specific a:any
at the end. And it works as expected.
But, what if I put it at the beginning:
function bar(a: any): any; function bar(a: string): string; function bar(a: number): number; function bar(a: number | string | any) { return null as any } bar(2); // any bar('2') // any bar({}) // any}
All ReturnTypes are any
. Because less specific overloading is at the beginning.
Same here:
type A = (a: number) => numbertype B = (b: string) => stringtype C = (c: any) => anydeclare var foo: C & B & Afoo(2) // anyfoo('2') // anyfoo({}) // any
UPDATE
Let's dig into ConstructorParameters
. What does it mean?
// this is what ConstructorParameters doing under the hoodtype Check = A extends (a: infer A) => any ? A : never // numbertype Check2 = (A & B) extends (a: infer A) => any ? A : never // stringtype Check3 = (A & B & C) extends (a: infer A) => any ? A : never // any
It just takes the last intersected item and infers it's parameters.
So if I put A
as a last item, it will infer only A
params:
type Check4 = (C & B & A) extends (a: infer A) => any ? A : never // number
So if you are doing intersection of functions - you should treat is as overloading.
Edge case: if you have function types with generics - intersection it might not work. I don't know/understand why.