Generic Interfaces and Classes
Make interfaces and classes reusable across types with type parameters.
Syntax
class Box<T> { constructor(public value: T) {} }Interfaces and classes can be generic too. A generic container like a Box<T> can hold any type while keeping its contents fully typed.
This pattern powers reusable data structures such as stacks, queues, and result wrappers.
Example
Loading editorβ¦
Press Run to execute the code.
When to use it
- A generic Repository<T> interface defines CRUD methods so any entity type can have its own typed repository.
- A generic ApiResponse<T> interface wraps any data type in a consistent status/data envelope.
- A generic Pair<A, B> interface models two related values of potentially different types reused across the codebase.
More examples
Generic interface
Defines a generic interface to wrap any payload type in a consistent API envelope shape.
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
const userResponse: ApiResponse<{ name: string }> = {
data: { name: 'Alice' },
status: 200,
message: 'OK',
};Generic Repository interface
Implements a generic Repository<T> interface for User entities, showing how generic interfaces enable reusable contracts.
interface Repository<T> {
findById(id: number): T | undefined;
save(entity: T): void;
delete(id: number): void;
}
interface User { id: number; name: string; }
class UserRepo implements Repository<User> {
private store: User[] = [];
findById(id: number): User | undefined { return this.store.find(u => u.id === id); }
save(entity: User): void { this.store.push(entity); }
delete(id: number): void { this.store = this.store.filter(u => u.id !== id); }
}Generic class with constraint
A generic class constrained to comparable types (number | string) so the sort operation is safe.
class MinHeap<T extends number | string> {
private items: T[] = [];
insert(item: T): void {
this.items.push(item);
this.items.sort();
}
min(): T | undefined {
return this.items[0];
}
}
Discussion