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