diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c2a14e5b9a0..03b74110962 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2604,7 +2604,7 @@ namespace ts { return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral((name).expression.kind); } - // Return the inferred type for a binding element + /** Return the inferred type for a binding element */ function getTypeForBindingElement(declaration: BindingElement): Type { const pattern = declaration.parent; const parentType = getTypeForBindingElementParent(pattern.parent); @@ -2630,6 +2630,9 @@ namespace ts { // computed properties with non-literal names are treated as 'any' return anyType; } + if (declaration.initializer) { + getContextualType(declaration.initializer); + } // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. @@ -7825,11 +7828,14 @@ namespace ts { return undefined; } - // In a variable, parameter or property declaration with a type annotation, the contextual type of an initializer - // expression is the type of the variable, parameter or property. Otherwise, in a parameter declaration of a - // contextually typed function expression, the contextual type of an initializer expression is the contextual type - // of the parameter. Otherwise, in a variable or parameter declaration with a binding pattern name, the contextual - // type of an initializer expression is the type implied by the binding pattern. + // In a variable, parameter or property declaration with a type annotation, + // the contextual type of an initializer expression is the type of the variable, parameter or property. + // Otherwise, in a parameter declaration of a contextually typed function expression, + // the contextual type of an initializer expression is the contextual type of the parameter. + // Otherwise, in a variable or parameter declaration with a binding pattern name, + // the contextual type of an initializer expression is the type implied by the binding pattern. + // Otherwise, in a binding pattern inside a variable or parameter declaration, + // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. function getContextualTypeForInitializerExpression(node: Expression): Type { const declaration = node.parent; if (node === declaration.initializer) { @@ -7845,6 +7851,16 @@ namespace ts { if (isBindingPattern(declaration.name)) { return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true); } + if (isBindingPattern(declaration.parent)) { + const parentDeclaration = declaration.parent.parent; + const name = declaration.propertyName || declaration.name; + if (isVariableLike(parentDeclaration) && + parentDeclaration.type && + (name.kind === SyntaxKind.Identifier || name.kind == SyntaxKind.StringLiteral)) { + const text = (name).text; + return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text); + } + } } return undefined; }