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
{{ message }}
Repository navigation
Type guard using square bracket notation does not narrow type #28081
Search Terms:
type guard square bracket notation narrowing
Code
interfaceConfigType{[key: string]: boolean|{prop: string};}constconfig: ConfigType={works: {prop: 'foo'},'works-not': {prop: 'bar'},bool: true,};if(typeofconfig.works!=='boolean'){config.works.prop='test';}if(typeofconfig['works-not']!=='boolean'){config['works-not'].prop='test';// [ts] Property 'prop' does not exist on type 'false'.}
Expected behavior:
The type guard using square bracket notation narrows the type in the same way the type guard using dot notation does, resulting in no type errors in the above example.
Actual behavior:
The type guard specifically using square bracket notation does not narrow the type.
No, this is not a duplicate. It's a missed interaction between indexed access and index signatures, where property access + index signatures works.
Here's a smaller repro, without the dashed-name red herring:
The behaviour is the same if the discriminator is typeof config['works'] !== 'boolean', so I think it's just a failure of control flow from indexed access in this case.
Also note that if we have interface ConfigType { works: boolean | { prop: string } } then both statements work.
Reacted by Ryan Cavanaugh and Diego A. Zapata Häntsch
Just a drive by comment. We are working in Google internal TS to forbid using the prop access on index signature objects. The main reason is that to Closure prop access means safe to rename and index access means don't touch. This optimization pass is done without global knowledge (other than whats' coming externally) so its up to the developer to decide whether it is really "safe" to rename.
The transformation from foo.bar to foo['bar'] is mostly noop TS-wise, except for this issue.
Update: The PR is trivial and performance is, as expected, bad for probably-uncommon adversarial code. We need to discuss in the design meeting whether to take this change.
Activity
DanielRosenwasser commentedon Oct 24, 2018
Is this a duplicate of #10530? Andy (Andrewkraft) (@Andy-MS) Wesley Wigham (@weswigham)
sandersn commentedon Oct 24, 2018
No, this is not a duplicate. It's a missed interaction between indexed access and index signatures, where property access + index signatures works.
Here's a smaller repro, without the dashed-name red herring:
The behaviour is the same if the discriminator is
typeof config['works'] !== 'boolean', so I think it's just a failure of control flow from indexed access in this case.Also note that if we have
interface ConfigType { works: boolean | { prop: string } }then both statements work.rkirov commentedon Feb 25, 2019
Just a drive by comment. We are working in Google internal TS to forbid using the prop access on index signature objects. The main reason is that to Closure prop access means safe to rename and index access means don't touch. This optimization pass is done without global knowledge (other than whats' coming externally) so its up to the developer to decide whether it is really "safe" to rename.
The transformation from
foo.bartofoo['bar']is mostly noop TS-wise, except for this issue.sandersn commentedon May 20, 2019
Turns out this was just missing. It is super simple to add since it's the same code as property access. I just need to make sure performance is OK.
sandersn commentedon Jun 14, 2019
Update: The PR is trivial and performance is, as expected, bad for probably-uncommon adversarial code. We need to discuss in the design meeting whether to take this change.