Description
Example code:
type UnaryFunction = (arg1) => any;
type BinaryFunction = (arg1, arg2) => any;
let binaryFuncs: BinaryFunction[] = [];
let unaryFunc = arg1 => {};
let reduced = binaryFuncs.reduce((prev, next) => prev, unaryFunc);
// ACTUAL:
let f: UnaryFunction = reduced; // ERROR binary not assignable to unary
// EXPECTED:
let f: UnaryFunction = reduced; // OK - both lhs and rhs really are unary
The call to Array#reduce
in the above example definitely returns a unary function, but the type system erroneously infers the return type as a binary function.
This seems to be caused by the declaration order of the two overloads of Array#reduce
in lib.d.ts
. If the declaration order is reversed, the problem is solved.
The two overloaded declarations in lib.d.ts
are as follows:
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
The first overload matches the example with T=BinaryFunction
, since it satisfies the compiler's assignability checks. So the second overload is never considered, even though it is a strictly better match, with T=BinaryFunction
and U=UnaryFunction
.
Would it be possible to swap the overload order for Array#reduce
(and Array#reduceRight
) in lib.d.ts
to resolve this issue?