@@ -4196,6 +4196,14 @@ module ts {
4196
4196
return type ;
4197
4197
}
4198
4198
4199
+ function keepAssignableTypes ( type : Type , targetType : Type , assumeAssignable : boolean ) : Type {
4200
+ if ( type . flags & TypeFlags . Union ) {
4201
+ var types = ( < UnionType > type ) . types ;
4202
+ return getUnionType ( filter ( types , t => assumeAssignable ? isTypeAssignableTo ( t , targetType ) : ! isTypeAssignableTo ( t , targetType ) ) ) ;
4203
+ }
4204
+ return type ;
4205
+ }
4206
+
4199
4207
// Check if a given variable is assigned within a given syntax node
4200
4208
function isVariableAssignedWithin ( symbol : Symbol , node : Node ) : boolean {
4201
4209
var links = getNodeLinks ( node ) ;
@@ -4347,6 +4355,28 @@ module ts {
4347
4355
}
4348
4356
}
4349
4357
4358
+ function narrowPropTypeByStringTypeEquality ( type : Type , expr : BinaryExpression , assumeTrue : boolean ) : Type {
4359
+ var left = < PropertyAccess > expr . left ;
4360
+ var right = expr . right ;
4361
+ var right_t = checkExpression ( right ) ;
4362
+ if ( left . kind !== SyntaxKind . PropertyAccess || left . left . kind !== SyntaxKind . Identifier ||
4363
+ ! ( right_t . flags & TypeFlags . StringLiteral ) ||
4364
+ getResolvedSymbol ( < Identifier > left . left ) !== symbol ) {
4365
+ return type ;
4366
+ }
4367
+ var t = checkPropertyAccess ( left ) ;
4368
+ var smallerType = t ;
4369
+ if ( isTypeAssignableTo ( right_t , t ) ) {
4370
+ smallerType = right_t ;
4371
+ }
4372
+ var dummyProperties : SymbolTable = { } ;
4373
+ var dummyProperty = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , left . right . text ) ;
4374
+ dummyProperty . type = smallerType ;
4375
+ dummyProperties [ dummyProperty . name ] = dummyProperty ;
4376
+ var dummyType = createAnonymousType ( undefined , dummyProperties , emptyArray , emptyArray , undefined , undefined ) ;
4377
+ return keepAssignableTypes ( type , dummyType , assumeTrue ) ;
4378
+ }
4379
+
4350
4380
function narrowTypeByAnd ( type : Type , expr : BinaryExpression , assumeTrue : boolean ) : Type {
4351
4381
if ( assumeTrue ) {
4352
4382
// The assumed result is true, therefore we narrow assuming each operand to be true.
@@ -4404,7 +4434,11 @@ module ts {
4404
4434
case SyntaxKind . BinaryExpression :
4405
4435
var operator = ( < BinaryExpression > expr ) . operator ;
4406
4436
if ( operator === SyntaxKind . EqualsEqualsEqualsToken || operator === SyntaxKind . ExclamationEqualsEqualsToken ) {
4407
- return narrowTypeByEquality ( type , < BinaryExpression > expr , assumeTrue ) ;
4437
+ if ( ( < BinaryExpression > expr ) . left . kind === SyntaxKind . PropertyAccess ) {
4438
+ return narrowPropTypeByStringTypeEquality ( type , < BinaryExpression > expr , assumeTrue ) ;
4439
+ } else {
4440
+ return narrowTypeByEquality ( type , < BinaryExpression > expr , assumeTrue ) ;
4441
+ }
4408
4442
}
4409
4443
else if ( operator === SyntaxKind . AmpersandAmpersandToken ) {
4410
4444
return narrowTypeByAnd ( type , < BinaryExpression > expr , assumeTrue ) ;
0 commit comments