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

Type narrowing for Union Types with instanceof #18498

Closed
gamli opened this issue Sep 15, 2017 · 4 comments
Closed

Type narrowing for Union Types with instanceof #18498

gamli opened this issue Sep 15, 2017 · 4 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@gamli
Copy link

gamli commented Sep 15, 2017

TypeScript Version: 2.4.0

Code

class Bird {
   fly() {
   }
}

class Fish {
   swim() {
   }
}

function moveAnimal(animal: Bird | Fish) {
   if (animal instanceof Bird) {
      // type is narrowed down to Bird => OK
      animal.fly();
   } else {
      // type is narrowed down to Fish => WRONG
      animal.swim();
   }
}

moveAnimal(
   {
      fly() {
      }
   });

Expected behavior:
Parameter animal should still be of type Bird | Fish in the else case.

Actual behavior:
Type is narrowed to Fish which leads to an error if called with a parameter of a type that is structurally compatible with Bird | Fish but is neither an instance of the Bird or Fish class. This seems to be related to some other issues related to the nominal typing of instanceof in combination with TypeScript's structural typing.

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Sep 15, 2017
@RyanCavanaugh
Copy link
Member

You can add a private field to each class to prevent this.

In general people either fall into the camp of "Only use new and instanceof works" or "Sometimes use object literals and don't use instanceof". We don't have syntax for determining which camp you want to be in for each particular class and don't intend to add it.

@gamli
Copy link
Author

gamli commented Sep 18, 2017

Is a special syntax even necessary? The animal parameter could be left as Bird | Fish in the else case. According to #1719 this should already be the case (until it changed since version 1.4).

@RyanCavanaugh
Copy link
Member

Nearly everyone would consider that behavior to be a bug. Evidence from the linked issue is that no code in the real world does an instanceof check and then doesn't assume the other member of the union in the else branch

@mhegazy
Copy link
Contributor

mhegazy commented Oct 2, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Oct 2, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants