Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita5c7201

Browse files
committed
Merge pull requestmicrosoft#4656 from Microsoft/Fix4655
Report error for class expressions incorrectly extending abstract classes
2 parents971c777 +d8c6f7e commita5c7201

File tree

6 files changed

+75
-10
lines changed

6 files changed

+75
-10
lines changed

‎src/compiler/checker.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5111,8 +5111,8 @@ namespace ts {
51115111
function abstractSignatureRelatedTo(source: Type, sourceSig: Signature, target: Type, targetSig: Signature) {
51125112
if (sourceSig && targetSig) {
51135113

5114-
let sourceDecl = source.symbol &&getDeclarationOfKind(source.symbol, SyntaxKind.ClassDeclaration);
5115-
let targetDecl = target.symbol &&getDeclarationOfKind(target.symbol, SyntaxKind.ClassDeclaration);
5114+
let sourceDecl = source.symbol &&getClassLikeDeclarationOfSymbol(source.symbol);
5115+
let targetDecl = target.symbol &&getClassLikeDeclarationOfSymbol(target.symbol);
51165116

51175117
if (!sourceDecl) {
51185118
// If the source object isn't itself a class declaration, it can be freely assigned, regardless
@@ -5126,8 +5126,8 @@ namespace ts {
51265126
let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature);
51275127
let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature);
51285128

5129-
let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol &&getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration);
5130-
let targetReturnDecl = targetReturnType && targetReturnType.symbol &&getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration);
5129+
let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol &&getClassLikeDeclarationOfSymbol(sourceReturnType.symbol);
5130+
let targetReturnDecl = targetReturnType && targetReturnType.symbol &&getClassLikeDeclarationOfSymbol(targetReturnType.symbol);
51315131
let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract;
51325132
let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract;
51335133

@@ -8879,7 +8879,7 @@ namespace ts {
88798879
// Note, only class declarations can be declared abstract.
88808880
// In the case of a merged class-module or class-interface declaration,
88818881
// only the class declaration node will have the Abstract flag set.
8882-
let valueDecl = expressionType.symbol &&getDeclarationOfKind(expressionType.symbol, SyntaxKind.ClassDeclaration);
8882+
let valueDecl = expressionType.symbol &&getClassLikeDeclarationOfSymbol(expressionType.symbol);
88838883
if (valueDecl && valueDecl.flags & NodeFlags.Abstract) {
88848884
error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(valueDecl.name));
88858885
return resolveErrorCall(node);
@@ -12631,6 +12631,10 @@ namespace ts {
1263112631
return s.flags & SymbolFlags.Instantiated ? getSymbolLinks(s).target : s;
1263212632
}
1263312633

12634+
function getClassLikeDeclarationOfSymbol(symbol: Symbol): Declaration {
12635+
return forEach(symbol.declarations, d => isClassLike(d) ? d : undefined);
12636+
}
12637+
1263412638
function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: ObjectType): void {
1263512639

1263612640
// TypeScript 1.0 spec (April 2014): 8.2.3
@@ -12668,14 +12672,20 @@ namespace ts {
1266812672
if (derived === base) {
1266912673
// derived class inherits base without override/redeclaration
1267012674

12671-
let derivedClassDecl =getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
12675+
let derivedClassDecl =getClassLikeDeclarationOfSymbol(type.symbol);
1267212676

1267312677
// It is an error to inherit an abstract member without implementing it or being declared abstract.
1267412678
// If there is no declaration for the derived class (as in the case of class expressions),
1267512679
// then the class cannot be declared abstract.
12676-
if ( baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
12677-
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
12678-
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
12680+
if (baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
12681+
if (derivedClassDecl.kind === SyntaxKind.ClassExpression) {
12682+
error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
12683+
symbolToString(baseProperty), typeToString(baseType));
12684+
}
12685+
else {
12686+
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
12687+
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
12688+
}
1267912689
}
1268012690
}
1268112691
else {

‎src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ namespace ts {
427427
Cannot_emit_namespaced_JSX_elements_in_React:{code:2650,category:DiagnosticCategory.Error,key:"Cannot emit namespaced JSX elements in React"},
428428
A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums:{code:2651,category:DiagnosticCategory.Error,key:"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums."},
429429
Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead:{code:2652,category:DiagnosticCategory.Error,key:"Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead."},
430+
Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1:{code:2653,category:DiagnosticCategory.Error,key:"Non-abstract class expression does not implement inherited abstract member '{0}' from class '{1}'."},
430431
Import_declaration_0_is_using_private_name_1:{code:4000,category:DiagnosticCategory.Error,key:"Import declaration '{0}' is using private name '{1}'."},
431432
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1:{code:4002,category:DiagnosticCategory.Error,key:"Type parameter '{0}' of exported class has or is using private name '{1}'."},
432433
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1:{code:4004,category:DiagnosticCategory.Error,key:"Type parameter '{0}' of exported interface has or is using private name '{1}'."},

‎src/compiler/diagnosticMessages.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1692,11 +1692,16 @@
16921692
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
16931693
"category":"Error",
16941694
"code":2651
1695-
},
1695+
},
16961696
"Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead.": {
16971697
"category":"Error",
16981698
"code":2652
16991699
},
1700+
"Non-abstract class expression does not implement inherited abstract member '{0}' from class '{1}'.": {
1701+
"category":"Error",
1702+
"code":2653
1703+
},
1704+
17001705
"Import declaration '{0}' is using private name '{1}'.": {
17011706
"category":"Error",
17021707
"code":4000
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/compiler/classExpressionExtendingAbstractClass.ts(5,9): error TS2653: Non-abstract class expression does not implement inherited abstract member 'foo' from class 'A'.
2+
3+
4+
==== tests/cases/compiler/classExpressionExtendingAbstractClass.ts (1 errors) ====
5+
abstract class A {
6+
abstract foo(): void;
7+
}
8+
9+
var C = class extends A { // no error reported!
10+
~~~~~
11+
!!! error TS2653: Non-abstract class expression does not implement inherited abstract member 'foo' from class 'A'.
12+
};
13+
14+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [classExpressionExtendingAbstractClass.ts]
2+
abstractclassA{
3+
abstractfoo():void;
4+
}
5+
6+
varC=classextendsA{// no error reported!
7+
};
8+
9+
10+
11+
//// [classExpressionExtendingAbstractClass.js]
12+
var__extends=(this&&this.__extends)||function(d,b){
13+
for(varpinb)if(b.hasOwnProperty(p))d[p]=b[p];
14+
function__(){this.constructor=d;}
15+
d.prototype=b===null ?Object.create(b) :(__.prototype=b.prototype,new__());
16+
};
17+
varA=(function(){
18+
functionA(){
19+
}
20+
returnA;
21+
})();
22+
varC=(function(_super){
23+
__extends(class_1,_super);
24+
functionclass_1(){
25+
_super.apply(this,arguments);
26+
}
27+
returnclass_1;
28+
})(A);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
abstractclassA{
2+
abstractfoo():void;
3+
}
4+
5+
varC=classextendsA{// no error reported!
6+
};
7+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp