Implement and Extend Interfaces with Classes in TypeScript

You’re building a user module for an app. You get API data, validate it, and create objects that follow a strict shape. But things get messy when multiple objects need the same structure and behavior.

This is where extending interfaces with classes in TypeScript becomes useful. You define a contract using an interface and enforce it using a class, so your code stays clean and predictable.

In this article, I’ll show you 4 ways to extend interfaces with classes in TypeScript.

Method 1 – Implement a Basic Interface in a Class

Use this when you want a class to strictly follow a defined structure.

Step 1: Create an Interface

interface User {
id: number;
name: string;
email: string;
}

How does this code work?
An interface defines the shape of an object. Here, any object of type User must have id, name, and email.

Step 2: Implement the Interface in a Class

class UserModel implements User {
id: number;
name: string;
email: string;

constructor(id: number, name: string, email: string) {
this.id = id;
this.name = name;
this.email = email;
}
}

How does this code work?
The implements keyword forces the class to include all properties from the User interface. If you miss one, the TypeScript compiler throws an error.

Step 3: Use the Class

const user = new UserModel(1, "John", "john@example.com");
console.log(user);

Expected Output:

UserModel { id: 1, name: 'John', email: 'john@example.com' }

You can refer to the screenshot below to see the output.

Implement and Extend Interfaces with Classes TypeScript

Pro Tip: Use implements to enforce structure, especially when working with API responses or form data.

Method 2 – Extend an Interface and Implement It in a Class

Use this when you want to build on an existing interface.

Step 1: Create a Base Interface

interface User {
id: number;
name: string;
}

Step 2: Extend the Interface

interface Admin extends User {
role: string;
}

How does this code work?
The extends keyword lets one interface inherit properties from another. Admin now includes id, name, and role.

Step 3: Implement Extended Interface in Class

class AdminUser implements Admin {
id: number;
name: string;
role: string;

constructor(id: number, name: string, role: string) {
this.id = id;
this.name = name;
this.role = role;
}
}

const admin = new AdminUser(1, "John", "Manager");

console.log(admin);

Expected Output:

AdminUser { id: 1, name: 'John', role: 'Manager' }

You can refer to the screenshot below to see the output.

Implement and Extend Interfaces with Classes in TypeScript

Pro Tip: Extend interfaces when your data grows over time instead of duplicating fields.

Method 3 – Implement Multiple Interfaces in One Class

Use this when a class needs to follow multiple contracts.

Step 1: Define Multiple Interfaces

interface User {
id: number;
name: string;
}

interface Logger {
log(message: string): void;
}

Step 2: Implement Both Interfaces

class UserService implements User, Logger {
id: number;
name: string;

constructor(id: number, name: string) {
this.id = id;
this.name = name;
}

log(message: string): void {
console.log("Log:", message);
}
}

How does this code work?
The class implements both User and Logger. It must define all properties and methods from both interfaces.

Step 3: Use the Class

const service = new UserService(1, "John");
service.log("User created");

Expected Output:

Log: User created

You can refer to the screenshot below to see the output.

Implement and Extend TypeScript Interfaces with Classes

Pro Tip: This pattern works well in enterprise apps where classes handle multiple responsibilities like logging, validation, or API calls.

Method 4 – Combine Interfaces with Generics in Classes

Use this when your data structure is dynamic but still needs type safety.

Step 1: Create a Generic Interface

interface ApiResponse<T> {
data: T;
status: number;
}

How does this code work?
A generic allows you to define a flexible type. T acts as a placeholder for any type.

Step 2: Implement in a Class

class ResponseHandler<T> implements ApiResponse<T> {
data: T;
status: number;

constructor(data: T, status: number) {
this.data = data;
this.status = status;
}
}

Step 3: Use with Different Types

const userResponse = new ResponseHandler<UserModel>(
new UserModel(1, "John", "john@example.com"),
200
);

console.log(userResponse);

Expected Output:

{ data: { id: 1, name: 'John', email: 'john@example.com' }, status: 200 }

Pro Tip: Generics help maintain type safety while handling reusable logic like API responses or utility services.

Things to Keep in Mind

  • implements vs extends: Use implements for TypeScript classes and extends for interfaces. They serve different purposes.
  • Missing properties: If a class skips any interface property, TypeScript throws a compile-time error.
  • Optional properties: Mark optional fields with ? in interfaces to avoid strict errors.
  • Strict mode issues: Enable strict in tsconfig to catch missing or incorrect types early.
  • Avoid any type: Use unknown instead of any when you’re unsure about data shape.
  • Interface vs type: Interfaces work better with classes, while type aliases are more flexible for unions.

You learned how to use classes with interfaces using basic implementation, interface extension, multiple interfaces, and generics.
Use simple implements for strict structure, extend interfaces for scalability, and use generics for flexible data handling.

You may also read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.