You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Consider re-ordering Array#reduce overloads in lib.d.ts #7014
typeUnaryFunction=(arg1)=>any;typeBinaryFunction=(arg1,arg2)=>any;letbinaryFuncs: BinaryFunction[]=[];letunaryFunc=arg1=>{};letreduced=binaryFuncs.reduce((prev,next)=>prev,unaryFunc);// ACTUAL:letf: UnaryFunction=reduced;// ERROR binary not assignable to unary// EXPECTED:letf: 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:
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?
changed the title [-]Type inference problem with Array.reduce (lib.d.ts)[/-][+]Consider re-ordering Array#reduce overloads in lib.d.ts[/+]on Feb 11, 2016
I believe it's safe to do this now -- the order we had was dependent on behavior that is no longer the case (ancient history, see http://typescript.codeplex.com/workitem/2352).
Glad this can now be resolved, and I really appreciate the effort the team takes in polishing these corner cases.
As a side not, I really dislike the argument ordering that TC39 chose for Array.prototype.reduce and Array.prototype.reduceRight. The seed should come first, not just because it makes type inference easier, but because it makes things more readable. Anyway, that decision is ancient history, but I wanted to rant about it.
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 Troy Gerwien (@yortus) example, this:
Taking PRs on this with the caveat we're still not 100% sure this is going to be an overall improvement, so reserving the right to reject it if it turns out to be bad on net.
Type 'string | number' is not assignable to type'string'.
Type 'number' is not assignable to type'string'.
2 const str: string = A.reduce((str, a) => `${str}${a.toString}`, '') ~~~
there is an easy enough workaround for now, i.e. A.map(_ => _.toString()).reduce(...), but this seems worth fixing?
Type 'string | number' is not assignable to type'string'.
Type 'number' is not assignable to type'string'.
2 const str: string = A.reduce((str, a) => `${str}${a.toString}`, '') ~~~
there is an easy enough workaround for now, i.e. A.map(_ => _.toString()).reduce(...), but this seems worth fixing?
An easier workaround.We provide the generic paramater here, so it matches the second overload.
Activity
yortus commentedon Feb 11, 2016
Simpler example:
This doesn't compile, tsc reports
"Operator '+' cannot be applied to types '{}' and 'number'".In fact the code is fine and runs fine.
tsc took the first overload since it works with
T={}, so the second (correct) overload is not considered.In general, the second overload will always be skipped if
Uis assignable toT(in this example,numberis assignable to{}).Swapping the order of the two
Array#reduceoverloads inlib.d.tsfixes this.[-]Type inference problem with Array.reduce (lib.d.ts)[/-][+]Consider re-ordering Array#reduce overloads in lib.d.ts[/+]RyanCavanaugh commentedon Feb 12, 2016
I believe it's safe to do this now -- the order we had was dependent on behavior that is no longer the case (ancient history, see http://typescript.codeplex.com/workitem/2352).
yortus commentedon Feb 12, 2016
Wow, nice archaeological find 😄 Those were the days...
aluanhaddad commentedon Mar 11, 2016
Glad this can now be resolved, and I really appreciate the effort the team takes in polishing these corner cases.
As a side not, I really dislike the argument ordering that TC39 chose for
Array.prototype.reduceandArray.prototype.reduceRight. The seed should come first, not just because it makes type inference easier, but because it makes things more readable. Anyway, that decision is ancient history, but I wanted to rant about it.johnnyreilly commentedon Apr 4, 2016
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 Troy Gerwien (@yortus) example, this:
Becomes:
RyanCavanaugh commentedon Jun 9, 2016
Taking PRs on this with the caveat we're still not 100% sure this is going to be an overall improvement, so reserving the right to reject it if it turns out to be bad on net.
vilicvane commentedon Sep 25, 2016
I am on this PR.bdurrani commentedon Oct 2, 2018
Looks like vilic took care of this issue. maybe this issue should be closed? It's been around for awhile. Ryan Cavanaugh (@RyanCavanaugh)
vilicvane commentedon Oct 2, 2018
Bilal Durrani (@bdurrani) Just noticed that I closed the PR myself. Might had encountered some problem but forgot to update the comment here.
chriskrycho commentedon Dec 19, 2019
This appears to still be an issue. Anyone know why #11356 ended up closed? vilic?
starpit commentedon Dec 20, 2019
agreed, we encounter this with typescript 3.7.3
which results in this compilation error:
there is an easy enough workaround for now, i.e.
A.map(_ => _.toString()).reduce(...), but this seems worth fixing?Meowu commentedon Feb 21, 2020
An easier workaround.We provide the generic paramater here, so it matches the second overload.
okmttdhr commentedon Mar 31, 2020
SCWR commentedon Sep 2, 2021
may be fix this with typescript 4.2.2?
fix(lib): reorder Array#reduce/reduceRight overloads in lib.d.ts
fix(lib): reorder Array#reduce/reduceRight overloads in lib.d.ts