You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classAnimal{privatex: number=0;}classCatextendsAnimal{publicwhiskers: number=1;}classBroom{privatey: number=1;publicwhiskers: number=1;publichandle: number=3;}functionhasWhiskers(input: Animal|Broom): input is Cat|Broom{returninputinstanceofCat||inputinstanceofBroom;}functionincorrect(input: Animal|Broom): number{if(hasWhiskers(input)){// INCORRECT: There should be a compiler error here, // but `input` got incorrectly narrowed to `Broom` // (instead of `Cat | Broom`)returninput.handle;}return-1;}functioncorrect(input: Animal|Broom): number{if(inputinstanceofCat||inputinstanceofBroom){// CORRECT: `handle` is not a member of `Cat | Broom`,// so the compiler correctly reports an error here.returninput.handle;}return-1;}constcat=newCat();// Prints "undefined" because cat.handle didn't actually existconsole.log(incorrect(cat));
But it can also be reproduced using simpler interface inheritance, like this:
interfaceAnimal{legs: number;}interfaceCatextendsAnimal{whiskers: number;}interfaceBroom{whiskers: number;handle: number;}functionhasWhiskers(input: Animal|Broom): input is Cat|Broom{returnObject.hasOwnProperty.call(input,'whiskers');}functionincorrect(input: Animal|Broom): number{if(hasWhiskers(input)){// INCORRECT: There should be a compiler error here, // but `input` got incorrectly narrowed to `Broom` // (instead of `Cat | Broom`)returninput.handle;}return-1;}
Expected behavior:
One would expect identical type narrowing when extracting this:
functionhasWhiskers(input: Animal|Broom): input is Cat|Broom{returninputinstanceofCat||inputinstanceofBroom;}...functionf(input: Animal|Broom): number {if(hasWhiskers(input)){...
Actual behavior:
The type is incorrectly narrowed to Broom instead of Cat | Broom.
As a result, clearly incorrect code compiles without any error.
TypeScript Version: 4.1.2
Search Terms:
narrowing
narrowed
type guard
type union
Code
@MickeyPhoenix encountered this bug while implementing type guards for HBOMax data services. The original repro involves
class
inheritance, like this:playground link
But it can also be reproduced using simpler
interface
inheritance, like this:playground link
Expected behavior:
One would expect identical type narrowing when extracting this:
...into this:
Actual behavior:
The type is incorrectly narrowed to
Broom
instead ofCat | Broom
.As a result, clearly incorrect code compiles without any error.
Related Issues: #31156
The text was updated successfully, but these errors were encountered: