Skip to content

Commit 58753bb

Browse files
committed
Add error for failing to mark an mixin class as abstract
1 parent 2e77e93 commit 58753bb

File tree

7 files changed

+39
-18
lines changed

7 files changed

+39
-18
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34616,8 +34616,16 @@ namespace ts {
3461634616
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
3461734617
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
3461834618
}
34619-
if (baseConstructorType.flags & TypeFlags.TypeVariable && !isMixinConstructorType(staticType)) {
34620-
error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
34619+
if (baseConstructorType.flags & TypeFlags.TypeVariable) {
34620+
if (!isMixinConstructorType(staticType)) {
34621+
error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
34622+
}
34623+
else {
34624+
const constructSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
34625+
if (constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) && !hasSyntacticModifier(node, ModifierFlags.Abstract)) {
34626+
error(node.name || node, Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract);
34627+
}
34628+
}
3462134629
}
3462234630

3462334631
if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) {

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,6 +3028,10 @@
30283028
"category": "Error",
30293029
"code": 2792
30303030
},
3031+
"A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.": {
3032+
"category": "Error",
3033+
"code": 2793
3034+
},
30313035

30323036
"Import declaration '{0}' is using private name '{1}'.": {
30333037
"category": "Error",

tests/baselines/reference/mixinAbstractClasses.2.errors.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(20,7): error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
2-
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(24,1): error TS2511: Cannot create an instance of an abstract class.
1+
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(7,11): error TS2793: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
2+
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(21,7): error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
3+
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(25,1): error TS2511: Cannot create an instance of an abstract class.
34

45

5-
==== tests/cases/conformance/classes/mixinAbstractClasses.2.ts (2 errors) ====
6+
==== tests/cases/conformance/classes/mixinAbstractClasses.2.ts (3 errors) ====
67
interface Mixin {
78
mixinMethod(): void;
89
}
910

1011
function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
11-
abstract class MixinClass extends baseClass implements Mixin {
12+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
13+
class MixinClass extends baseClass implements Mixin {
14+
~~~~~~~~~~
15+
!!! error TS2793: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
1216
mixinMethod() {
1317
}
1418
}

tests/baselines/reference/mixinAbstractClasses.2.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ interface Mixin {
44
}
55

66
function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
7-
abstract class MixinClass extends baseClass implements Mixin {
7+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
8+
class MixinClass extends baseClass implements Mixin {
89
mixinMethod() {
910
}
1011
}
@@ -26,6 +27,7 @@ new MixedBase();
2627

2728
//// [mixinAbstractClasses.2.js]
2829
function Mixin(baseClass) {
30+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
2931
class MixinClass extends baseClass {
3032
mixinMethod() {
3133
}

tests/baselines/reference/mixinAbstractClasses.2.symbols

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,39 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
1616
>args : Symbol(args, Decl(mixinAbstractClasses.2.ts, 4, 122))
1717
>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
1818

19-
abstract class MixinClass extends baseClass implements Mixin {
19+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
20+
class MixinClass extends baseClass implements Mixin {
2021
>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
2122
>baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.2.ts, 4, 70))
2223
>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
2324

2425
mixinMethod() {
25-
>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.2.ts, 5, 66))
26+
>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.2.ts, 6, 57))
2627
}
2728
}
2829
return MixinClass;
2930
>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
3031
}
3132

3233
abstract class AbstractBase {
33-
>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
34+
>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 11, 1))
3435

3536
abstract abstractBaseMethod(): void;
36-
>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 12, 29))
37+
>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 13, 29))
3738
}
3839

3940
const MixedBase = Mixin(AbstractBase);
40-
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
41+
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
4142
>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
42-
>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
43+
>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 11, 1))
4344

4445
// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
4546
class DerivedFromAbstract extends MixedBase {
46-
>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.2.ts, 16, 38))
47-
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
47+
>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.2.ts, 17, 38))
48+
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
4849
}
4950

5051
// error expected: Cannot create an instance of an abstract class.
5152
new MixedBase();
52-
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
53+
>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
5354

tests/baselines/reference/mixinAbstractClasses.2.types

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
1010
>baseClass : TBaseClass
1111
>args : any
1212

13-
abstract class MixinClass extends baseClass implements Mixin {
13+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
14+
class MixinClass extends baseClass implements Mixin {
1415
>MixinClass : MixinClass
1516
>baseClass : TBaseClass
1617

tests/cases/conformance/classes/mixinAbstractClasses.2.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ interface Mixin {
66
}
77

88
function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
9-
abstract class MixinClass extends baseClass implements Mixin {
9+
// error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
10+
class MixinClass extends baseClass implements Mixin {
1011
mixinMethod() {
1112
}
1213
}

0 commit comments

Comments
 (0)