diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da002607ed82c..082254ce20e1f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31789,6 +31789,9 @@ namespace ts { function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) { if (isClassLike(node.parent)) { + if (isStringLiteral(node.name) && node.name.text === "constructor") { + return grammarErrorOnNode(node.name, Diagnostics.Classes_may_not_have_a_field_named_constructor); + } if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 417f8004d7326..c44f4f8b20f8c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4958,5 +4958,9 @@ "Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '[\"constructor\"]()' to write a method.": { "category": "Error", "code": 18005 + }, + "Classes may not have a field named 'constructor'.": { + "category": "Error", + "code": 18006 } } diff --git a/tests/baselines/reference/propertyNamedConstructor.errors.txt b/tests/baselines/reference/propertyNamedConstructor.errors.txt new file mode 100644 index 0000000000000..e275131a50c36 --- /dev/null +++ b/tests/baselines/reference/propertyNamedConstructor.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts(2,3): error TS18006: Classes may not have a field named 'constructor'. + + +==== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts (1 errors) ==== + class X1 { + "constructor" = 3; // Error + ~~~~~~~~~~~~~ +!!! error TS18006: Classes may not have a field named 'constructor'. + } + + class X2 { + ["constructor"] = 3; + } + \ No newline at end of file diff --git a/tests/baselines/reference/propertyNamedConstructor.js b/tests/baselines/reference/propertyNamedConstructor.js new file mode 100644 index 0000000000000..8b7752ab6d558 --- /dev/null +++ b/tests/baselines/reference/propertyNamedConstructor.js @@ -0,0 +1,23 @@ +//// [propertyNamedConstructor.ts] +class X1 { + "constructor" = 3; // Error +} + +class X2 { + ["constructor"] = 3; +} + + +//// [propertyNamedConstructor.js] +var X1 = /** @class */ (function () { + function X1() { + this["constructor"] = 3; // Error + } + return X1; +}()); +var X2 = /** @class */ (function () { + function X2() { + this["constructor"] = 3; + } + return X2; +}()); diff --git a/tests/baselines/reference/propertyNamedConstructor.symbols b/tests/baselines/reference/propertyNamedConstructor.symbols new file mode 100644 index 0000000000000..b8a028d8444b8 --- /dev/null +++ b/tests/baselines/reference/propertyNamedConstructor.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts === +class X1 { +>X1 : Symbol(X1, Decl(propertyNamedConstructor.ts, 0, 0)) + + "constructor" = 3; // Error +>"constructor" : Symbol(X1["constructor"], Decl(propertyNamedConstructor.ts, 0, 10)) +} + +class X2 { +>X2 : Symbol(X2, Decl(propertyNamedConstructor.ts, 2, 1)) + + ["constructor"] = 3; +>["constructor"] : Symbol(X2["constructor"], Decl(propertyNamedConstructor.ts, 4, 10)) +>"constructor" : Symbol(X2["constructor"], Decl(propertyNamedConstructor.ts, 4, 10)) +} + diff --git a/tests/baselines/reference/propertyNamedConstructor.types b/tests/baselines/reference/propertyNamedConstructor.types new file mode 100644 index 0000000000000..6b90f31e917ad --- /dev/null +++ b/tests/baselines/reference/propertyNamedConstructor.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts === +class X1 { +>X1 : X1 + + "constructor" = 3; // Error +>"constructor" : number +>3 : 3 +} + +class X2 { +>X2 : X2 + + ["constructor"] = 3; +>["constructor"] : number +>"constructor" : "constructor" +>3 : 3 +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts new file mode 100644 index 0000000000000..49c53a9894f05 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyNamedConstructor.ts @@ -0,0 +1,7 @@ +class X1 { + "constructor" = 3; // Error +} + +class X2 { + ["constructor"] = 3; +}