Skip to content
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

Incorrect handling of unions of arrays. #12829

Closed
domoritz opened this issue Dec 10, 2016 · 5 comments
Closed

Incorrect handling of unions of arrays. #12829

domoritz opened this issue Dec 10, 2016 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@domoritz
Copy link

TypeScript Version: 2.1

Code

This code works although the type of the forEach callback is not suffuient.

const a: boolean[] | number[] = [1,1,1];
a.forEach((b: number) => console.log);

But this fails (which is expected)

const a: boolean[] | number[] = [1,1,1];
a.forEach((b: boolean) => console.log);

I'd expect only this code to be valid

const a: boolean[] | number[] = [1,1,1];
a.forEach((b: boolean | number) => console.log);

I understand that boolean[] | number[] is a subtype of (boolean | number)[] and would expect typescript to be stricter if I provide the former.

@ahejlsberg
Copy link
Member

Your first example compiles because control flow analysis has determined the type of a to be number[] at the call to forEach because the preceding assignment assigned an array literal of type number[].

domoritz added a commit to vega/vega-lite that referenced this issue Dec 11, 2016
@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label Dec 11, 2016
@domoritz
Copy link
Author

This is the smallest example I could create to recreate an issue.

In

channelEncoding.forEach(function(fieldDef: FieldDef | OrderChannelDef) {
  fields.push(field(fieldDef));
});

I know that channelEncoding is a FieldDef[] | OrderChannelDef[].

But I get the following error

[ts] Cannot invoke an expression whose type lacks a call signature. Type '((callbackfn: (value: FieldDef, index: number, array: FieldDef[]) => void, thisArg?: any) => void...' has no compatible call signatures.

Yes, the error is slightly different but I thought that was because ts handles complex types differently from simple types.

I thought this error is caused by the behavior of the flow analysis (which is being smarter than my explicit type annotations).

domoritz added a commit to vega/vega-lite that referenced this issue Dec 11, 2016
@ahejlsberg
Copy link
Member

This error is reported because forEach has a different signature in each of the two arrays, so there is not a common signature we can use in the call expression. You can help by providing a type assertion:

(channelEncoding as (FieldDef | OrderChannelDef)[]).forEach(...)

Alternatively, you could change channelEncoding to have type (FieldDef | OrderChannelDef)[]. It is slightly less strict (because it allows mixed arrays), but probably easier to work with.

@ahejlsberg
Copy link
Member

For more discussion see #10620.

@domoritz
Copy link
Author

Thanks for the explanation! The behavior I posted above is still a bit odd (flow analysis overrides my explicit annotation) but I don't have a problem with it.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

2 participants