diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5b70c70ae4b..03934153e4f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -783,6 +783,10 @@ "category": "Error", "code": 1245 }, + "An interface property cannot have an initializer.": { + "category": "Error", + "code": 1246 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", @@ -2418,7 +2422,7 @@ "Not all code paths return a value.": { "category": "Error", "code": 7030 - }, + }, "You cannot rename this element.": { "category": "Error", "code": 8000 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 212594f7b7d..36819061696 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2230,6 +2230,7 @@ namespace ts { const fullStart = scanner.getStartPos(); const name = parsePropertyName(); const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + const modifiers = parseModifiers(); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { const method = createNode(SyntaxKind.MethodSignature, fullStart); @@ -2247,6 +2248,26 @@ namespace ts { property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); + + // Although interfaces cannot not have initializers, we attempt to parse an initializer + // so we can report that an interface cannot have an initializer. + // + // For instance properties specifically, since they are evaluated inside the constructor, + // we do *not * want to parse yield expressions, so we specifically turn the yield context + // off. The grammar would look something like this: + // + // MemberVariableDeclaration[Yield]: + // AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initialiser_opt[In]; + // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initialiser_opt[In, ?Yield]; + // + // The checker may still error in the static case to explicitly disallow the yield expression. + const initializer = modifiers && modifiers.flags & NodeFlags.Static + ? allowInAnd(parseNonParameterInitializer) + : doOutsideOfContext(ParserContextFlags.Yield | ParserContextFlags.DisallowIn, parseNonParameterInitializer); + if (initializer !== undefined) { + parseErrorAtCurrentToken(Diagnostics.An_interface_property_cannot_have_an_initializer); + } + parseTypeMemberSemicolon(); return finishNode(property); }