Closed
Description
TypeScript Version: 3.3.0-dev.20181128
Search Terms: symbol, property, key, type inference, does not narrow, union type, different behavior of symbol and string keys
Code
const LOADED = Symbol();
class Entity {
[LOADED]: true = true;
doStuff() { }
}
class ReferenceToEntity {
[LOADED]: false = false;
}
class SomeClass {
entity?: Entity | ReferenceToEntity;
foo() {
this.entity && this.entity[LOADED] && this.entity.doStuff();
} // ^^^^^^^ ERROR!
}
Expected behavior:
Since Entity[LOADED]
is of type true
and ReferenceToEntity[LOADED]
is of type false
, I would expect the type of this.entity
to be narrowed to just Entity
in foo()
and the above example to compile, just like it does with string property keys – i.e. this behavior seems to be unique to Symbol
properties.
Actual behavior:
Compilation error:
Property 'doStuff' does not exist on type 'Entity | ReferenceToEntity'.
Property 'doStuff' does not exist on type 'ReferenceToEntity'.
Things that do not change the behavior:
- marking
[LOADED]
asreadonly
- explicitly marking
LOADED
asunique symbol
- turning
[LOADED]
into a getter, i.e.get [LOADED](): true { return true; }
- disabling strict mode
Things that change the behavior:
- using string property keys makes it work as intended, i.e. the compiler realizes that if
this.entity.loaded
is truthy thenthis.entity
˙must be anEntity
- assigning to
entity
infoo()
just before thedoStuff()
call also makes it work:foo() { this.entity = new Entity(); this.entity && this.entity[LOADED] && this.entity.doStuff(); // NO ERROR }
Related Issues: