mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Check for class expressions as well as class declarations
This commit is contained in:
parent
5542e396d7
commit
3a08af1450
@ -12625,6 +12625,10 @@ namespace ts {
|
||||
return s.flags & SymbolFlags.Instantiated ? getSymbolLinks(s).target : s;
|
||||
}
|
||||
|
||||
function getClassLikeDeclarationOfSymbol(symbol: Symbol): Declaration {
|
||||
return forEach(symbol.declarations, d => isClassLike(d) ? d : undefined);
|
||||
}
|
||||
|
||||
function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: ObjectType): void {
|
||||
|
||||
// TypeScript 1.0 spec (April 2014): 8.2.3
|
||||
@ -12662,14 +12666,20 @@ namespace ts {
|
||||
if (derived === base) {
|
||||
// derived class inherits base without override/redeclaration
|
||||
|
||||
let derivedClassDecl = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
|
||||
let derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol);
|
||||
|
||||
// It is an error to inherit an abstract member without implementing it or being declared abstract.
|
||||
// If there is no declaration for the derived class (as in the case of class expressions),
|
||||
// then the class cannot be declared abstract.
|
||||
if ( baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
|
||||
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
|
||||
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
|
||||
if (baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
|
||||
if (derivedClassDecl.kind === SyntaxKind.ClassExpression) {
|
||||
error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
|
||||
symbolToString(baseProperty), typeToString(baseType));
|
||||
}
|
||||
else {
|
||||
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
|
||||
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@ -427,6 +427,7 @@ namespace ts {
|
||||
Cannot_emit_namespaced_JSX_elements_in_React: { code: 2650, category: DiagnosticCategory.Error, key: "Cannot emit namespaced JSX elements in React" },
|
||||
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." },
|
||||
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." },
|
||||
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}'." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
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}'." },
|
||||
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}'." },
|
||||
|
||||
@ -1692,11 +1692,16 @@
|
||||
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
|
||||
"category": "Error",
|
||||
"code": 2651
|
||||
},
|
||||
},
|
||||
"Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead.": {
|
||||
"category": "Error",
|
||||
"code": 2652
|
||||
},
|
||||
"Non-abstract class expression does not implement inherited abstract member '{0}' from class '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2653
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
tests/cases/compiler/classExpressionExtendingAbstractClass.ts(5,9): error TS2653: Non-abstract class expression does not implement inherited abstract member 'foo' from class 'A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/classExpressionExtendingAbstractClass.ts (1 errors) ====
|
||||
abstract class A {
|
||||
abstract foo(): void;
|
||||
}
|
||||
|
||||
var C = class extends A { // no error reported!
|
||||
~~~~~
|
||||
!!! error TS2653: Non-abstract class expression does not implement inherited abstract member 'foo' from class 'A'.
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
//// [classExpressionExtendingAbstractClass.ts]
|
||||
abstract class A {
|
||||
abstract foo(): void;
|
||||
}
|
||||
|
||||
var C = class extends A { // no error reported!
|
||||
};
|
||||
|
||||
|
||||
|
||||
//// [classExpressionExtendingAbstractClass.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
})();
|
||||
var C = (function (_super) {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return class_1;
|
||||
})(A);
|
||||
@ -0,0 +1,7 @@
|
||||
abstract class A {
|
||||
abstract foo(): void;
|
||||
}
|
||||
|
||||
var C = class extends A { // no error reported!
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user