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.
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.
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.
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).
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript