@@ -29319,7 +29319,7 @@ namespace ts {
29319
29319
29320
29320
// NOTE: assignability is checked in checkClassDeclaration
29321
29321
const baseProperties = getPropertiesOfType(baseType);
29322
- for (const baseProperty of baseProperties) {
29322
+ outer: for (const baseProperty of baseProperties) {
29323
29323
const base = getTargetSymbol(baseProperty);
29324
29324
29325
29325
if (base.flags & SymbolFlags.Prototype) {
@@ -29331,60 +29331,71 @@ namespace ts {
29331
29331
29332
29332
Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration.");
29333
29333
29334
- if (derived) {
29335
- // In order to resolve whether the inherited method was overridden in the base class or not,
29336
- // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated*
29337
- // type declaration, derived and base resolve to the same symbol even in the case of generic classes.
29338
- if (derived === base) {
29339
- // derived class inherits base without override/redeclaration
29340
-
29341
- const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol)!;
29342
-
29343
- // It is an error to inherit an abstract member without implementing it or being declared abstract.
29344
- // If there is no declaration for the derived class (as in the case of class expressions),
29345
- // then the class cannot be declared abstract.
29346
- if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasModifier(derivedClassDecl, ModifierFlags.Abstract))) {
29347
- if (derivedClassDecl.kind === SyntaxKind.ClassExpression) {
29348
- error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
29349
- symbolToString(baseProperty), typeToString(baseType));
29350
- }
29351
- else {
29352
- error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
29353
- typeToString(type), symbolToString(baseProperty), typeToString(baseType));
29334
+ // In order to resolve whether the inherited method was overridden in the base class or not,
29335
+ // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated*
29336
+ // type declaration, derived and base resolve to the same symbol even in the case of generic classes.
29337
+ if (derived === base) {
29338
+ // derived class inherits base without override/redeclaration
29339
+
29340
+ const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol)!;
29341
+
29342
+ // It is an error to inherit an abstract member without implementing it or being declared abstract.
29343
+ // If there is no declaration for the derived class (as in the case of class expressions),
29344
+ // then the class cannot be declared abstract.
29345
+ if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasModifier(derivedClassDecl, ModifierFlags.Abstract))) {
29346
+ // getPropertyOfObjectType will return a single symbol even if the property can be found
29347
+ // on multiple declarations, so it’s possible for derived === base to be true even when
29348
+ // another base type introduced from declaration merging to contain the property as well,
29349
+ // which should satisfy the abstract member requirement.
29350
+ for (const otherBaseType of getBaseTypes(type)) {
29351
+ if (otherBaseType === baseType) continue;
29352
+ const baseSymbol = getPropertyOfObjectType(otherBaseType, base.escapedName);
29353
+ const derivedElsewhere = baseSymbol && getTargetSymbol(baseSymbol);
29354
+ if (derivedElsewhere && derivedElsewhere !== base) {
29355
+ continue outer;
29354
29356
}
29355
29357
}
29356
- }
29357
- else {
29358
- // derived overrides base.
29359
- const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived);
29360
- if (baseDeclarationFlags & ModifierFlags.Private || derivedDeclarationFlags & ModifierFlags.Private) {
29361
- // either base or derived property is private - not override, skip it
29362
- continue;
29363
- }
29364
29358
29365
- if (isPrototypeProperty(base) || base.flags & SymbolFlags.PropertyOrAccessor && derived.flags & SymbolFlags.PropertyOrAccessor ) {
29366
- // method is overridden with method or property/accessor is overridden with property/accessor - correct case
29367
- continue ;
29359
+ if (derivedClassDecl.kind === SyntaxKind.ClassExpression ) {
29360
+ error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
29361
+ symbolToString(baseProperty), typeToString(baseType)) ;
29368
29362
}
29369
-
29370
- let errorMessage: DiagnosticMessage;
29371
- if (isPrototypeProperty(base)) {
29372
- if (derived.flags & SymbolFlags.Accessor) {
29373
- errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
29374
- }
29375
- else {
29376
- errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
29377
- }
29363
+ else {
29364
+ error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
29365
+ typeToString(type), symbolToString(baseProperty), typeToString(baseType));
29378
29366
}
29379
- else if (base.flags & SymbolFlags.Accessor) {
29380
- errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
29367
+ }
29368
+ }
29369
+ else {
29370
+ // derived overrides base.
29371
+ const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived);
29372
+ if (baseDeclarationFlags & ModifierFlags.Private || derivedDeclarationFlags & ModifierFlags.Private) {
29373
+ // either base or derived property is private - not override, skip it
29374
+ continue;
29375
+ }
29376
+
29377
+ if (isPrototypeProperty(base) || base.flags & SymbolFlags.PropertyOrAccessor && derived.flags & SymbolFlags.PropertyOrAccessor) {
29378
+ // method is overridden with method or property/accessor is overridden with property/accessor - correct case
29379
+ continue;
29380
+ }
29381
+
29382
+ let errorMessage: DiagnosticMessage;
29383
+ if (isPrototypeProperty(base)) {
29384
+ if (derived.flags & SymbolFlags.Accessor) {
29385
+ errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
29381
29386
}
29382
29387
else {
29383
- errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function ;
29388
+ errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property ;
29384
29389
}
29385
-
29386
- error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
29387
29390
}
29391
+ else if (base.flags & SymbolFlags.Accessor) {
29392
+ errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
29393
+ }
29394
+ else {
29395
+ errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
29396
+ }
29397
+
29398
+ error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
29388
29399
}
29389
29400
}
29390
29401
}
0 commit comments