From d73fb3acdd33712b7d6267e8fc11173596c3e07a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 09:48:36 -0800 Subject: [PATCH] Narrow property access from string index signatures Previously these accesses did not use control flow to narrow property accesses of undefined properties that are resolved from a string index signature. Now the use control flow to narrow these just like normal properties. --- src/compiler/checker.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7bce66892d..e2a419900c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15221,7 +15221,7 @@ namespace ts { if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - return indexInfo.type; + return getFlowTypeOfPropertyAccess(node, /*prop*/ undefined, indexInfo.type, getAssignmentTargetKind(node)); } if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type); @@ -15246,16 +15246,21 @@ namespace ts { return unknownType; } } + return getFlowTypeOfPropertyAccess(node, prop, propType, assignmentKind); + } - // Only compute control flow type if this is a property access expression that isn't an - // assignment target, and the referenced property was declared as a variable, property, - // accessor, or optional method. - if (node.kind !== SyntaxKind.PropertyAccessExpression || assignmentKind === AssignmentKind.Definite || - !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && - !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { - return propType; + /** + * Only compute control flow type if this is a property access expression that isn't an + * assignment target, and the referenced property was declared as a variable, property, + * accessor, or optional method. + */ + function getFlowTypeOfPropertyAccess(node: PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, type: Type, assignmentKind: AssignmentKind) { + if (node.kind !== SyntaxKind.PropertyAccessExpression || + assignmentKind === AssignmentKind.Definite || + prop && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && type.flags & TypeFlags.Union)) { + return type; } - const flowType = getFlowTypeOfReference(node, propType); + const flowType = getFlowTypeOfReference(node, type); return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; }