Consider re-ordering Array#reduce overloads in lib.d.ts
See original GitHub issueExample 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?
Issue Analytics
- State:
- Created 8 years ago
- Reactions:5
- Comments:14 (8 by maintainers)
Top GitHub Comments
Just stumbled on this - look forward to this being resolved! For anyone else wondering what to do in the interim just supply the type parameter. So to take @yortus example, this:
Becomes:
I re-created the PR https://github.com/microsoft/TypeScript/pull/37702 Can anybody check this?