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
Hey all, I stumbled upon an oddity around type narrowing. I've been meaning to report for ages but... well better late than never!
Code
interfaceOneThing{oneThing: {};}interfaceOtherThing{otherThing: {};}constreturnOneThingOrAnother=()=>'5'===`${6}`// ignore this - what's produced is what matters
? {oneThing: {}}asOneThing
: {otherThing: {}}asOtherThing;constiHaveOneThingOrAnother=returnOneThingOrAnother();if(iHaveOneThingOrAnother.oneThing){// iHaveOneThingOrAnother should be narrowed to OneThing}else{// iHaveOneThingOrAnother should be narrowed to OtherThing}
Expected behavior:
I would expect type narrowing to occur in the manner suggested in the comments.
Actual behavior:
Actually the expected type narrowing does not occur. Rather, the if (iHaveOneThingOrAnother.oneThing) { expression throws the following exception:
Property 'oneThing' does not exist on type 'OneThing | OtherThing'.
Property 'oneThing' does not exist on type 'OtherThing'.
Why? Obviously I could solve this by introducing a user defined type guard but that seems like it ought not to be necessary.
Is there a reason the TypeScript compiler does not perform the type narrowing in the way I had hoped?
Good question. We consider this to be an unsafe operation because we can't guarantee something like this doesn't happen:
interfaceGotString{x: string;}interfaceGotNumber{y: number;}constfooled={x: 100,y: 200};constgn: GotNumber=fooled;constj: GotString|GotNumber=Math.random()>0.5 ? gn : {x: 'ok'};if(j.x){// In theory: j: GotStringj.x.substr(0);// Crash - x was a number. Bamboozled!}
See also #14094 where it's proposed to add syntax to create these sorts of unions automatically.
Thanks for the response @RyanCavanaugh - that makes sense.
I'm quite keen on exclusive unions so at present I'm landed with either introducing a type guard or casting back to any briefly - neither of which is attractive. Suffice to say I like the look of #14094!
Do feel free to close this issue if you think it's covered by #14094. Good to know the reason for this 👍
TypeScript Version: 2.4.1
Hey all, I stumbled upon an oddity around type narrowing. I've been meaning to report for ages but... well better late than never!
Code
Expected behavior:
I would expect type narrowing to occur in the manner suggested in the comments.
Actual behavior:
Actually the expected type narrowing does not occur. Rather, the
if (iHaveOneThingOrAnother.oneThing) {
expression throws the following exception:Why? Obviously I could solve this by introducing a user defined type guard but that seems like it ought not to be necessary.
Is there a reason the TypeScript compiler does not perform the type narrowing in the way I had hoped?
Possibly related to #12457 but not certain.
Much ❤️ for all your work BTW 🌻
The text was updated successfully, but these errors were encountered: