How to fix Non-abstract class 'X' does not implement inherited abstract member 'Y' in TypeScript
This TypeScript error occurs when a concrete class extends an abstract base class but fails to implement all abstract members. The error ensures that derived classes fulfill the contract defined by their abstract parent classes.
Quick fix
Fixes Non-abstract class 'X' does not implement inherited abstract member 'Y'
abstract class Animal {
abstract makeSound(): void;
abstract move(distance: number): void;
}
// ❌ Error: Non-abstract class 'Dog' does not implement
// inherited abstract member 'move' from class 'Animal'
class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
// Missing move() implementation
}- Identify all missing abstract members
- Implement all abstract members with correct signatures
- Check inheritance chain for multiple abstract classes
- Verify method signatures match exactly
abstract class Animal {abstract makeSound(): void;abstract move(distance: number): void;}// ❌ Error: Non-abstract class 'Dog' does not implement// inherited abstract member 'move' from class 'Animal'class Dog extends Animal {makeSound(): void {console.log("Woof");}// Missing move() implementation}Non-abstract class 'X' does not implement inherited abstract member 'Y'
What this error means
In TypeScript, abstract classes serve as base classes that define a contract through abstract members (methods, properties, getters, or setters). Abstract members declare what must be implemented but don't provide the implementation themselves. When a concrete (non-abstract) class extends an abstract class, it must implement every abstract member inherited from its parent. If any abstract member remains unimplemented, TypeScript raises this error because the class would be incomplete and couldn't be instantiated. This is TypeScript's way of enforcing the "contract" pattern where abstract classes define requirements that all concrete subclasses must satisfy. It prevents runtime errors by catching missing implementations at compile time.
Typical symptoms
- TypeScript compiler error when extending an abstract class
- Build fails with error mentioning "does not implement inherited abstract member"
- IDE shows red squiggly lines on the class declaration
- Cannot instantiate the derived class with new keyword
- Error message lists specific abstract members that are missing implementations
Common causes
- Forgot to implement one or more abstract methods from the parent abstract class
- Misspelled method names when implementing abstract members
- Incorrect method signatures (different parameters or return types)
- Extending multiple levels of abstract classes and missing implementations from intermediate classes
- Using wrong access modifiers (public/private/protected) on implementations
How to fix "Non-abstract class 'X' does not implement inherited abstract member 'Y'"
First, check the error message to see which abstract members are missing implementations. The error will list them explicitly:
abstract class Animal {
abstract makeSound(): void;
abstract move(distance: number): void;
}
// ❌ Error: Non-abstract class 'Dog' does not implement
// inherited abstract member 'move' from class 'Animal'
class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
// Missing move() implementation
}Look at the parent abstract class definition to see the exact signatures required.
Add implementations for every abstract member, matching the exact signatures from the parent class:
abstract class Animal {
abstract makeSound(): void;
abstract move(distance: number): void;
}
class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
move(distance: number): void { // ✅ Correct signature
console.log(`Running ${distance} meters`);
}
}
const dog = new Dog(); // ✅ Now works
dog.makeSound(); // "Woof"
dog.move(10); // "Running 10 meters"Pay attention to:
- Method names (case-sensitive)
- Parameter types and names
- Return types
- Access modifiers (public/protected)
If you have multiple levels of inheritance, ensure all abstract members from the entire chain are implemented:
abstract class LivingThing {
abstract breathe(): void;
}
abstract class Animal extends LivingThing {
abstract makeSound(): void;
// breathe() is still abstract here
}
class Dog extends Animal {
breathe(): void { // ✅ From LivingThing
console.log("Breathing...");
}
makeSound(): void { // ✅ From Animal
console.log("Woof");
}
}Or make intermediate classes abstract if they don't implement everything:
abstract class LivingThing {
abstract breathe(): void;
}
abstract class Animal extends LivingThing {
abstract makeSound(): void;
// breathe() not implemented here - still abstract
}
abstract class Mammal extends Animal {
breathe(): void { // ✅ Implements breathe() from LivingThing
console.log("Breathing with lungs");
}
// makeSound() still abstract
}
class Dog extends Mammal {
makeSound(): void { // ✅ Final implementation
console.log("Woof");
}
}Abstract implementations must match the parent signatures exactly. Common mismatches include:
abstract class Example {
abstract process(data: string): number;
abstract get value(): string;
}
class Implementation extends Example {
// ❌ Wrong return type
process(data: string): string {
return data;
}
// ❌ Wrong - should be getter, not method
value(): string {
return "value";
}
}
class CorrectImplementation extends Example {
// ✅ Correct return type
process(data: string): number {
return data.length;
}
// ✅ Correct getter syntax
get value(): string {
return "value";
}
}Use your IDE's "Go to Definition" feature to see the exact abstract member signatures.
If your class can't or shouldn't implement all abstract members (perhaps it's meant to be further extended), mark it as abstract:
abstract class Animal {
abstract makeSound(): void;
abstract move(): void;
}
// Can't implement move() yet? Make it abstract
abstract class Bird extends Animal {
makeSound(): void {
console.log("Chirp");
}
// move() still abstract - birds move differently
}
class Penguin extends Bird {
move(): void { // ✅ Penguin implements the specific movement
console.log("Waddling");
}
}
class Sparrow extends Bird {
move(): void { // ✅ Different implementation
console.log("Flying");
}
}This creates a proper inheritance hierarchy where each level can partially implement the contract.
If you're having trouble with the inheritance model, consider whether interfaces might be a better fit:
// With abstract class (requires inheritance)
abstract class Animal {
abstract makeSound(): void;
move(): void { // Concrete method
console.log("Moving");
}
}
// With interfaces (more flexible)
interface Animal {
makeSound(): void;
move(): void;
}
class Dog implements Animal {
makeSound(): void {
console.log("Woof");
}
move(): void {
console.log("Running");
}
}
// Can implement multiple interfaces
interface Pet {
name: string;
}
class NamedDog implements Animal, Pet {
constructor(public name: string) {}
makeSound(): void {
console.log(`${this.name} says Woof`);
}
move(): void {
console.log(`${this.name} is running`);
}
}Interfaces provide more flexibility for composition over inheritance.
Advanced notes
TypeScript's abstract class system is a compile-time feature that doesn't exist in JavaScript output. The abstract keyword and related checks are stripped during compilation.
When working with complex inheritance hierarchies:
1. Every class in the chain must either implement all abstract members or be marked abstract
2. You can have abstract classes that extend other abstract classes
3. The final concrete class in any inheritance chain must implement all accumulated abstract members
Common patterns:
- Template Method: Abstract class defines algorithm skeleton with abstract steps
- Factory Method: Abstract class declares factory method, subclasses implement it
- Bridge: Separate abstraction from implementation using abstract classes
Performance considerations: Abstract classes have no runtime overhead compared to interfaces. The choice between abstract classes and interfaces depends on whether you need to share implementation (use abstract class) or just structure (use interface).
Frequently asked questions
- What does "Non-abstract class 'X' does not implement inherited abstract member 'Y" mean?
- In TypeScript, abstract classes serve as base classes that define a contract through abstract members (methods, properties, getters, or setters). Abstract members declare what must be implemented but don't provide the implementation themselves. When a concrete (non-abstract) class extends an abstract class, it must implement every abstract member inherited from its parent.
- How do I fix "Non-abstract class 'X' does not implement inherited abstract member 'Y"?
- This TypeScript error occurs when a concrete class extends an abstract base class but fails to implement all abstract members. The error ensures that derived classes fulfill the contract defined by their abstract parent classes.
- What causes "Non-abstract class 'X' does not implement inherited abstract member 'Y"?
- Forgot to implement one or more abstract methods from the parent abstract class Misspelled method names when implementing abstract members Incorrect method signatures (different parameters or return types)
- Is the "Non-abstract class 'X' does not implement inherited abstract member 'Y" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖Typescriptlang.org - classes.html(Official Docs)
- 🐙Github.com - 680(GitHub)
- 🐙Github.com - 57240(GitHub)
- 📖Typescriptlang.org - typescript-4-3.html(Official Docs)
- 💬