From cd0d3babe9d4d79b51fa75c55707901a6579d92f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 8 Jul 2015 19:04:58 -0700 Subject: [PATCH] Object literals can only have properties that exist in contextual type --- src/compiler/checker.ts | 15 +++++++++++++++ .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1edd2a7a920..29922f17e33 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6830,6 +6830,18 @@ namespace ts { return links.resolvedType; } + function isPermittedProperty(contextualType: Type, propName: string): boolean { + if (contextualType.flags & TypeFlags.ObjectType) { + let resolved = resolveStructuredTypeMembers(contextualType); + return !!(resolved.properties.length === 0 || resolved.stringIndexType || + resolved.numberIndexType || getPropertyOfObjectType(contextualType, propName)); + } + if (contextualType.flags & TypeFlags.UnionOrIntersection) { + return !forEach((contextualType).types, type => !isPermittedProperty(type, propName)); + } + return true; + } + function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type { // Grammar checking checkGrammarObjectLiteralExpression(node); @@ -6879,6 +6891,9 @@ namespace ts { if (!hasDynamicName(memberDecl)) { propertiesTable[member.name] = member; + if (contextualType && !isPermittedProperty(contextualType, member.name)) { + error(memberDecl.name, Diagnostics.Property_0_does_not_exist_in_contextual_type_1, member.name, typeToString(contextualType)); + } } propertiesArray.push(member); } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index a17f8857590..33f30abc4ab 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -414,6 +414,7 @@ namespace ts { The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { code: 2522, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression." }, yield_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2523, category: DiagnosticCategory.Error, key: "'yield' expressions cannot be used in a parameter initializer." }, await_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2524, category: DiagnosticCategory.Error, key: "'await' expressions cannot be used in a parameter initializer." }, + Property_0_does_not_exist_in_contextual_type_1: { code: 2525, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist in contextual type '{1}'." }, JSX_element_attributes_type_0_must_be_an_object_type: { code: 2600, category: DiagnosticCategory.Error, key: "JSX element attributes type '{0}' must be an object type." }, The_return_type_of_a_JSX_element_constructor_must_return_an_object_type: { code: 2601, category: DiagnosticCategory.Error, key: "The return type of a JSX element constructor must return an object type." }, JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist: { code: 2602, category: DiagnosticCategory.Error, key: "JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 94be4f53c97..8036009b974 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1645,6 +1645,10 @@ "category": "Error", "code": 2524 }, + "Property '{0}' does not exist in contextual type '{1}'.": { + "category": "Error", + "code": 2525 + }, "JSX element attributes type '{0}' must be an object type.": { "category": "Error", "code": 2600