TypeScript: Wrongly infers any[] from Array.prototype.flat, Array.prototype.concat
TypeScript Version: 3.2.4, 3.3.0-dev.20190126
Search Terms: array, flat, concat, any, unsound
Code
const a: boolean[] = [[17], ["foo"]].flat(); // wrongly accepted
const b: boolean[] = Array.prototype.concat([17], [19], [21]); // wrongly accepted
Using tsc --strict -t esnext
.
(What I’m really trying to do: find a type safe way to concatenate an array of arrays. It’d be nice if [].concat(...arrays)
were accepted, which I think would be a consequence of #26976, but that’s not the issue I’m reporting here. arrays.flat()
and Array.prototype.concat(...arrays)
are accepted but apparently provide no type safety.)
Expected behavior: [[17], ["foo"]].flat()
should be typed (number | string)[]
(if it’s accepted at all), and Array.prototype.concat([17], [19], [21])
should be typed number[]
. In both cases the assignment to boolean[]
should be rejected.
Actual behavior: TypeScript infers any[]
for both right hand sides (even with --noImplicitAny
implied by --strict
), and accepts the assignments to boolean[]
with no complaints.
Playground Link: Playground doesn’t support esnext
, but here’s the second line.
Related Issues: #19535 for concat
(but that one may have more to do with the difficulty of typing concat
’s weird behavior when non-arrays are passed?), #26976
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 2
- Comments: 28 (10 by maintainers)
The array element type should be unwrappable pretty easily:
If I do so then I get correct errors:
produces
One option that would improve type safety would be to change the
any[]
overload offlat()
tounknown[]
and likewise for the typing ofArray.prototype
. This would force you to use a type assertion and prevent accidents like in the OP, but I don’t know whether it would go against that “balance between correctness and productivity”; in my experience the design seems to deliberately avoid creating situations that force a cast and prefer to useany
in these situations. BUT I admit the possibility that that might only be becauseunknown
is relatively new. 😄@RyanCavanaugh The goalposts didn’t move as a result of the discussion AFAIK, the issue is still as described in the OP.
Anyway, I’ve put in my 2c (there, um, may have been
somea lot of inflation), so I’ll duck out at this point and we can wait to see what the TS team thinks about this.