Repository navigation
'in' expression should be a type guard #1427
Description
Activity
- addedSuggestionAn idea for TypeScriptAn idea for TypeScript
on Dec 10, 2014 There's a hidden trap inherent in using property existence to distinguish the types in a union: imagine if elsewhere in the code there is a type
interface I2Ext extends I2 { p: number; }, and an I2Ext makes its way into the function that uses p to distinguish I1 | I2. Any time you extend a type and add a property you'd have to worry about whether the name you picked will cause it to be misidentified somewhere...This could be made safe if there were a way to specify that an object lacks a certain property, and that were used to determine which parts of a union get narrowed away when
inevaluates to true.JsonFreeman commented
on Dec 10, 2014 ContributorAuthorMore actionsYes, that is a great point. I think the crux of it is that you can't eliminate a constituent based on the fact that it lacks a property you observe to be present. But as you alluded to, if there were an else block, it would be safe to narrow there based on the observation that a property is absent.
JsonFreeman commented
on Dec 10, 2014 ContributorAuthorMore actionsDan Quirk (@danquirk) This problem that jeffreymorlan points out applies to property accesses as well.
- addedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
on Dec 17, 2014 RyanCavanaugh commented
on Dec 17, 2014 MemberMore actionsWe should look at how prevalent this "assume X based on presence of Y" pattern is in real code.
Today we would have:
interface I1 { prop1: string; doSomething(): string; } interface I2 { prop2: string; doAnotherThing(): string; } class MyObject implements I2 { prop1: string = ""; prop2: string = ""; doAnotherThing() { return 'doAnotherThing'; } doSomething() { return 'doSomething'; } } function test(obj: I1 | I2) { if ('prop1' in obj) { alert('doSomething() = ' + (<I1> obj).doSomething()); } else { alert('doAnotherThing() = ' + (<I2> obj).doAnotherThing()); } } test(new MyObject);
As there's no type guard, I just type cast. I believe having 'in' as type guard is no more dangerous than a typecast. It's even a little better, perharps .
closing in favor of #10485
- addedDuplicateAn existing issue was already createdAn existing issue was already createdand removedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
on Sep 20, 2016 - locked and limited conversation to collaborators
on Jun 18, 2018
The in operator provides an opportunity for us to narrow a type. There are two ways that this could work: