From c68947e0fbbbe3c47c8d7608b6ee0d04d6325d38 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 29 Feb 2016 10:07:12 -0800 Subject: [PATCH] Contextually type initializers of binding elements Previously they were not contextually typed, which meant that lambdas got completely incorrect types, and that types that rely on contextual typing, like tuples and string literal types, did not work correctly. --- src/compiler/checker.ts | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) 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; }