This TypeScript error occurs when you declare abstract methods or properties in a class that is not itself marked as abstract. Abstract members can only exist in abstract classes that serve as base classes for inheritance.
In TypeScript, abstract members (methods, properties, getters, or setters) define a contract that must be implemented by subclasses. The abstract keyword signals that the member has no implementation and expects derived classes to provide one. This only makes sense in an abstract class, which cannot be instantiated directly. If you try to add abstract members to a regular concrete class, TypeScript raises this error because concrete classes must be fully implemented and directly instantiable. Abstract classes serve as templates for inheritance hierarchies where subclasses implement the contract.
If you intend to have abstract members, you must mark the entire class as abstract:
// ❌ Wrong - regular class with abstract member
class Animal {
abstract makeSound(): void;
}
// ✅ Correct - abstract class with abstract member
abstract class Animal {
abstract makeSound(): void;
}This tells TypeScript that Animal is a base class intended for inheritance, not direct instantiation.
Create concrete subclasses that implement all abstract members:
abstract class Animal {
abstract makeSound(): void;
abstract move(): void;
}
class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
move(): void {
console.log("Running on four legs");
}
}
const dog = new Dog(); // ✅ Now this works
dog.makeSound(); // "Woof"Derived classes must provide concrete implementations for every abstract member. Only the final concrete class in the hierarchy needs full implementation.
If your derived class still has unimplemented abstract members, it must also be marked abstract:
abstract class Animal {
abstract makeSound(): void;
abstract move(): void;
}
// ❌ Error - doesn't implement move() and isn't abstract
class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
}
// ✅ Correct - also abstract since move() not implemented
abstract class Dog extends Animal {
makeSound(): void {
console.log("Woof");
}
}
class Labrador extends Dog {
move(): void {
console.log("Running fast");
}
}This creates an inheritance chain where intermediate classes can be abstract, but only the final concrete class needs all members implemented.
If you realized you don't actually need abstract members in your class, simply remove the abstract keyword from the members:
// Before - incorrect abstract class
class Car {
abstract startEngine(): void;
}
// After - concrete implementation
class Car {
startEngine(): void {
console.log("Engine started");
}
}Use this approach only if you want a fully concrete class with no inheritance contract. Every class that isn't meant to be extended should have this concrete implementation.
Abstract classes are part of TypeScript's structural typing system and help enforce contracts in inheritance hierarchies. Every subclass in the chain must either implement all unimplemented abstract members or itself be marked abstract.
TypeScript will not allow you to instantiate any class (abstract or concrete) that has unimplemented abstract members. This is strictly enforced at compile time and does not appear in JavaScript output—abstract members are purely a TypeScript compile-time construct.
For mixins or composition patterns where you want to share behavior without strict inheritance, consider using interfaces instead of abstract classes. Interfaces define structure without implementation details.
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