Skip to content

Allow override as parameter property #43831

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40609,6 +40609,7 @@ namespace ts {
}
break;
case SyntaxKind.OverrideKeyword:
// If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property.
if (flags & ModifierFlags.Override) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override");
}
Expand All @@ -40621,9 +40622,6 @@ namespace ts {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async");
}
if (node.kind === SyntaxKind.Parameter) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "override");
}
flags |= ModifierFlags.Override;
lastOverride = modifier;
break;
Expand Down Expand Up @@ -40696,7 +40694,7 @@ namespace ts {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly");
}
else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) {
// If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property.
// If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property.
return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature);
}
flags |= ModifierFlags.Readonly;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ namespace ts {

AccessibilityModifier = Public | Private | Protected,
// Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property.
ParameterPropertyModifier = AccessibilityModifier | Readonly,
ParameterPropertyModifier = AccessibilityModifier | Readonly | Override,
NonPublicAccessibilityModifier = Private | Protected,

TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override,
Expand Down
2 changes: 1 addition & 1 deletion src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ namespace FourSlashInterface {
export const classElementInJsKeywords = getInJsKeywords(classElementKeywords);

export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] =
["private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({
["private", "protected", "public", "readonly", "override"].map((name): ExpectedCompletionEntryObject => ({
name,
kind: "keyword",
sortText: SortText.GlobalsOrKeywords
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ declare namespace ts {
Override = 16384,
HasComputedFlags = 536870912,
AccessibilityModifier = 28,
ParameterPropertyModifier = 92,
ParameterPropertyModifier = 16476,
NonPublicAccessibilityModifier = 24,
TypeScriptModifier = 18654,
ExportDefault = 513,
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ declare namespace ts {
Override = 16384,
HasComputedFlags = 536870912,
AccessibilityModifier = 28,
ParameterPropertyModifier = 92,
ParameterPropertyModifier = 16476,
NonPublicAccessibilityModifier = 24,
TypeScriptModifier = 18654,
ExportDefault = 513,
Expand Down
6 changes: 3 additions & 3 deletions tests/baselines/reference/override11.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/conformance/override/override11.ts(6,18): error TS1090: 'override' modifier cannot appear on a parameter.
tests/cases/conformance/override/override11.ts(6,27): error TS1029: 'public' modifier must precede 'override' modifier.


==== tests/cases/conformance/override/override11.ts (1 errors) ====
Expand All @@ -8,8 +8,8 @@ tests/cases/conformance/override/override11.ts(6,18): error TS1090: 'override' m

class Sub extends Base {
constructor (override public foo: number) {
~~~~~~~~
!!! error TS1090: 'override' modifier cannot appear on a parameter.
~~~~~~
!!! error TS1029: 'public' modifier must precede 'override' modifier.
super();
}
}
Expand Down
36 changes: 36 additions & 0 deletions tests/baselines/reference/overrideParameterProperty.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
tests/cases/conformance/override/overrideParameterProperty.ts(20,24): error TS1029: 'public' modifier must precede 'override' modifier.
tests/cases/conformance/override/overrideParameterProperty.ts(25,5): error TS2369: A parameter property is only allowed in a constructor implementation.


==== tests/cases/conformance/override/overrideParameterProperty.ts (2 errors) ====
class Base {
p1!: string;
}

class C1 extends Base {
constructor(public override p1: "hello") {
super();
this.p1;
}
}

class C2 extends Base {
constructor(override p1: "hello") {
super();
this.p1;
}
}

class C3 extends Base {
constructor(override public p1: "hello") {
~~~~~~
!!! error TS1029: 'public' modifier must precede 'override' modifier.
super();
this.p1;
}

m(override p1: "hello") {}
~~~~~~~~~~~~~~~~~~~~
!!! error TS2369: A parameter property is only allowed in a constructor implementation.
}

81 changes: 81 additions & 0 deletions tests/baselines/reference/overrideParameterProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//// [overrideParameterProperty.ts]
class Base {
p1!: string;
}

class C1 extends Base {
constructor(public override p1: "hello") {
super();
this.p1;
}
}

class C2 extends Base {
constructor(override p1: "hello") {
super();
this.p1;
}
}

class C3 extends Base {
constructor(override public p1: "hello") {
super();
this.p1;
}

m(override p1: "hello") {}
}


//// [overrideParameterProperty.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Base = /** @class */ (function () {
function Base() {
}
return Base;
}());
var C1 = /** @class */ (function (_super) {
__extends(C1, _super);
function C1(p1) {
var _this = _super.call(this) || this;
_this.p1 = p1;
_this.p1;
return _this;
}
return C1;
}(Base));
var C2 = /** @class */ (function (_super) {
__extends(C2, _super);
function C2(p1) {
var _this = _super.call(this) || this;
_this.p1 = p1;
_this.p1;
return _this;
}
return C2;
}(Base));
var C3 = /** @class */ (function (_super) {
__extends(C3, _super);
function C3(p1) {
var _this = _super.call(this) || this;
_this.p1 = p1;
_this.p1;
return _this;
}
C3.prototype.m = function (p1) { };
return C3;
}(Base));
63 changes: 63 additions & 0 deletions tests/baselines/reference/overrideParameterProperty.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
=== tests/cases/conformance/override/overrideParameterProperty.ts ===
class Base {
>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

p1!: string;
>p1 : Symbol(Base.p1, Decl(overrideParameterProperty.ts, 0, 12))
}

class C1 extends Base {
>C1 : Symbol(C1, Decl(overrideParameterProperty.ts, 2, 1))
>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

constructor(public override p1: "hello") {
>p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14))

super();
>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

this.p1;
>this.p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14))
>this : Symbol(C1, Decl(overrideParameterProperty.ts, 2, 1))
>p1 : Symbol(C1.p1, Decl(overrideParameterProperty.ts, 5, 14))
}
}

class C2 extends Base {
>C2 : Symbol(C2, Decl(overrideParameterProperty.ts, 9, 1))
>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

constructor(override p1: "hello") {
>p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14))

super();
>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

this.p1;
>this.p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14))
>this : Symbol(C2, Decl(overrideParameterProperty.ts, 9, 1))
>p1 : Symbol(C2.p1, Decl(overrideParameterProperty.ts, 12, 14))
}
}

class C3 extends Base {
>C3 : Symbol(C3, Decl(overrideParameterProperty.ts, 16, 1))
>Base : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

constructor(override public p1: "hello") {
>p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14))

super();
>super : Symbol(Base, Decl(overrideParameterProperty.ts, 0, 0))

this.p1;
>this.p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14))
>this : Symbol(C3, Decl(overrideParameterProperty.ts, 16, 1))
>p1 : Symbol(C3.p1, Decl(overrideParameterProperty.ts, 19, 14))
}

m(override p1: "hello") {}
>m : Symbol(C3.m, Decl(overrideParameterProperty.ts, 22, 3))
>p1 : Symbol(p1, Decl(overrideParameterProperty.ts, 24, 4))
}

66 changes: 66 additions & 0 deletions tests/baselines/reference/overrideParameterProperty.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
=== tests/cases/conformance/override/overrideParameterProperty.ts ===
class Base {
>Base : Base

p1!: string;
>p1 : string
}

class C1 extends Base {
>C1 : C1
>Base : Base

constructor(public override p1: "hello") {
>p1 : "hello"

super();
>super() : void
>super : typeof Base

this.p1;
>this.p1 : "hello"
>this : this
>p1 : "hello"
}
}

class C2 extends Base {
>C2 : C2
>Base : Base

constructor(override p1: "hello") {
>p1 : "hello"

super();
>super() : void
>super : typeof Base

this.p1;
>this.p1 : "hello"
>this : this
>p1 : "hello"
}
}

class C3 extends Base {
>C3 : C3
>Base : Base

constructor(override public p1: "hello") {
>p1 : "hello"

super();
>super() : void
>super : typeof Base

this.p1;
>this.p1 : "hello"
>this : this
>p1 : "hello"
}

m(override p1: "hello") {}
>m : (p1: "hello") => void
>p1 : "hello"
}

28 changes: 28 additions & 0 deletions tests/cases/conformance/override/overrideParameterProperty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @noImplicitOverride: true

class Base {
p1!: string;
}

class C1 extends Base {
constructor(public override p1: "hello") {
super();
this.p1;
}
}

class C2 extends Base {
constructor(override p1: "hello") {
super();
this.p1;
}
}

class C3 extends Base {
constructor(override public p1: "hello") {
super();
this.p1;
}

m(override p1: "hello") {}
}