-
Notifications
You must be signed in to change notification settings - Fork 12.8k
flatMap errors when callback returns certain union types #31033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
After playing around with the definition, this change using conditional types seems to make flatMap<U, This = undefined> (
- callback: (this: This, value: T, index: number, array: T[]) => U|ReadonlyArray<U>,
+ callback: (this: This, value: T, index: number, array: T[]) => U,
thisArg?: This
-): U[]
+): (U extends ReadonlyArray<infer V> ? V : U)[] |
It's not a bug. The signature correctly models the standard library behavior. |
It models a certain statically-typed interpretation of the behaviour, but there's nothing in the ES spec that prevents it. All flat/flatMap cares about is whether each element is an array (in which case it unwraps it), or not (in which case it leaves it alone), it doesn't say that the elements in the arrays being unwrapped must be the same type as the non-wrapped elements at the top level. Here's another, more contrived, example that currently errors in TS (but works fine in JS): [1, ['foo'], 2].flatMap(item => item) |
Correct. The callback could return
|
Can you show an example using my solution above where that would be the case? If there is value in being this inflexible I'd like to know where it lies. Even so, I had thought TypeScript was more descriptive than prescriptive.
Right, I'm not discounting that pattern, it's just that there is also a more general case here. |
I started to write an answer, but the bug tracker seems like an inappropriate forum. It works as designed. I encourage you to ask on Stack or Slack. You can |
The ES spec prevents almost nothing; see https://stackoverflow.com/questions/41750390/what-does-all-legal-javascript-is-legal-typescript-mean I think the normal use case for |
I agree - thanks for the tip, I didn't realize that would work. I still think there probably exists other "valid" use cases for a heterogeneously mapped array but admit I can't think of anything particularly compelling right now, and such cases could just do the same as above. However it does seem a little inconsistent then that plain |
TypeScript Version: 3.4.3
Search Terms: flat, flatmap
Code
Actual behavior:
With strict null checks on:
Turning strict null checks off prevents the error as you might expect, but that's obviously not desirable.
More generally, any callback that returns
foo[] | bar
(wherebar
is not compatible withfoo
) seems to run into the same issue. TheMap.prototype.get
example I've used here just seems like it would be a relatively common use case in particular (you'd typically follow it up by calling.filter(Boolean)
or similar on the mapped result).More code
Seeing if doing the operations separately will help:
Expected behavior:
flatMapped
/flattened
result to be inferred as(number | undefined)[]
.Playground Link:
Doesn't seem to be able to load the appropriate library definition, even with
/// <reference lib="es2019.array" />
Related Issues:
#29604 seems to be related to the
.flat()
part.The text was updated successfully, but these errors were encountered: