Skip to main content

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.
  • implements checks 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, B must satisfy both interfaces.
  • No runtime cost: interfaces are erased during compilation. Node sees plain JS classes.

Quick example

ts
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 Plugin forces 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

ts
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

ts
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

ts
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

ts
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

ts
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()); // 18

Both 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

ts
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 ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?