What does implements do in TypeScript?
implements in TypeScript is a compile-time contract: the class must match every member of the interface, or the compiler refuses to continue.
Theory
TL;DR
- Think of it as a compliance checklist. The interface is the inspector's requirements; the class is the kitchen being audited.
implementschecks shape, not behavior. Nothing from the interface is copied into the class.- Use it when you want a structural guarantee without inheritance.
class Foo implements A, Bmust satisfy both interfaces.- No runtime cost: interfaces are erased during compilation. Node sees plain JS classes.
Quick example
interface Shape {
area(): number;
}
class Circle implements Shape {
constructor(private radius: number) {}
area() {
return Math.PI * this.radius ** 2; // Required by Shape
}
}Remove area() and TypeScript reports: Property 'area' is missing in type 'Circle' but required in type 'Shape'. The compiled JS has no trace of the interface.
implements vs extends
extends copies parent class methods into the prototype chain. implements only checks shape, no code is transferred. This is why a class can implement multiple interfaces (implements A, B) but only extend one parent.
Pick implements when you want a structural contract without locking the class into a prototype chain. Pick extends when you need shared code.
When to use
- Plugin APIs:
class MyPlugin implements Pluginforces users to match your contract - NestJS guards and interceptors:
class AuthGuard implements CanActivate - Testing: ensures mock classes have every method the real class exposes
- Multiple behaviors on one class:
class Duck implements Flyable, Swimmable - Redux action creators:
class IncrementAction implements Action
How the compiler handles this
During tsc, TypeScript walks the class AST and checks every interface member against the class definition. A missing member or mismatched signature produces a compile error. Nothing from this process reaches the JS output. At runtime, V8 sees ordinary class syntax with no interface metadata.
Common mistakes
Expecting implements to copy implementation
interface HasGreet {
greet(): string;
}
class Bot implements HasGreet {
// Error: Property 'greet' is missing
}I've seen this in code reviews: someone adds implements and waits for the method to appear. It won't. Write it yourself.
Using implements with a concrete class instead of extends
class Animal {
move() {}
}
class Dog implements Animal { // Error: Property 'move' is missing
bark() {}
}If you want move() inherited, use extends Animal. With implements, every member must be defined manually regardless of whether the target is a class or interface.
Access modifier mismatch
interface User {
getName(): string;
}
class Admin implements User {
private getName() { return "admin"; } // Error: private breaks the public contract
}Interfaces describe the public API. Making a required method private violates the contract. Remove private or use public.
Forgetting ? on optional interface members
interface Swimmable {
swim?(): void; // Optional in the interface
}
class Duck implements Swimmable {
swim() { console.log("Paddle!"); } // Fine - optional means you can skip it too
}Remove the ? from the interface and swim() becomes required for every class that implements Swimmable. Easy to miss during refactoring.
Real-world usage
- NestJS:
class AuthGuard implements CanActivate,class Logger implements NestInterceptor - Express: middleware classes that match the middleware function signature
- React: mock implementations in Jest that match the real component API
- Vue 3 plugins:
class MyPlugin implements Plugin - Redux:
class IncrementAction implements Action
Follow-up questions
Q: What is the difference between implements and extends?
A: extends copies methods via the prototype chain and works only with classes. implements checks shape and works only with interfaces. A class can extend one parent but implement many interfaces.
Q: Can implements check private members?
A: No. Interfaces describe public shape only. A private method won't satisfy an interface requirement.
Q: What if two implemented interfaces have overlapping members with different return types?
A: TypeScript requires the class to satisfy both. Conflicting return types produce a compile error. There is no automatic resolution.
Q: How does implements interact with declaration merging?
A: If an interface is declared twice, TypeScript merges both into one combined shape. A class implementing that interface must satisfy both declarations. Declare Foo with a() and again with b(), and implements Foo requires both methods.
Examples
Basic: shape contract
interface Shape {
area(): number;
perimeter(): number;
}
class Rectangle implements Shape {
constructor(private width: number, private height: number) {}
area() {
return this.width * this.height;
}
perimeter() {
return 2 * (this.width + this.height);
}
}
const rect = new Rectangle(4, 5);
console.log(rect.area()); // 20
console.log(rect.perimeter()); // 18Both methods are required by the interface. Remove either and tsc stops the build with a clear error pointing to the missing member.
Intermediate: multiple interfaces
interface Flyable {
fly(): void;
}
interface Loggable {
log(message: string): void;
}
class Drone implements Flyable, Loggable {
fly() {
console.log("Drone is airborne");
}
log(message: string) {
console.log(`[Drone] ${message}`);
}
}
const drone = new Drone();
drone.fly(); // "Drone is airborne"
drone.log("Battery at 80%"); // "[Drone] Battery at 80%"Drone satisfies both contracts. The prototype chain stays flat. Add a third interface and the list grows without creating an inheritance hierarchy. That is composition without inheritance.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.