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

Using "instanceOf" seems to change the type of something to "never" #10966

Closed
dzearing opened this issue Sep 17, 2016 · 3 comments
Closed

Using "instanceOf" seems to change the type of something to "never" #10966

dzearing opened this issue Sep 17, 2016 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@dzearing
Copy link
Member

dzearing commented Sep 17, 2016

TypeScript Version: 2.0.2

Code

This works:

let foo: boolean[] = [];
return !!(foo.splice);

The following fails on referring to "splice" because after the instanceof evaluation, the "foo" object changes from type boolean[] to type never, which doesn't have splice defined:

let foo: boolean[] = [];
return (foo instanceof Array) || !!(foo.splice);

Strangely, if I change the condition to AND instead of OR, we don't have any issues:

let foo: boolean[] = [];
return (foo instanceof Array) && !!(foo.splice);

Or, if I change the order of evaluation, that works as well:

let foo: boolean[] = [];
return !!(foo.splice) || (foo instanceof Array);

Note, this isn't something specific to arrays. You can change the boolean[] to HTMLElement, same sort of problem.

Expected behavior:
No errors in this case.

Actual behavior:
Property 'splice' does not exist on type 'never'.

@dzearing
Copy link
Member Author

This seems very related to #10934

However I'm not sure completely. This seems very buggy and unexpected because I do not expect foo to change typings after a comparison. Code that was previously compiling fine is no longer compiling.

@ahejlsberg
Copy link
Member

@dzearing This is effectively the type checker telling you that the particular expression will never execute.

let foo: boolean[] = [];
return (foo instanceof Array) || !!(foo.splice);

In the foo instanceof Array check, the type checker narrows the type of foo to only the subset that are arrays. That turns out to be all possible values of foo, so foo has type boolean[] in the true branch. But in the false branch the type checker narrows to the subset that aren't arrays. That turns out to be nothing, so foo has type never in the false branch.

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 17, 2016
@dzearing
Copy link
Member Author

Oh man, awesome! I see it now! It really is "never". :) Thanks Anders.

@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