Can you make a generic class?
What a generic class is
A generic class is a class in which one or more types (for example, T, U, K, V)
are passed as parameters to make it flexible and type-safe.
It is not tied to a specific data type, but works with any type while keeping strict typing.
1. The simplest example
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}Usage:
const box1 = new Box<number>(123);
const box2 = new Box<string>("Hello");
console.log(box1.getValue()); // 123
console.log(box2.getValue()); // HelloHere T is a generic parameter:
- when creating
Box<number>→T = number, - when creating
Box<string>→T = string.
TypeScript makes sure the type stays consistent:
box1.getValue().toFixed(2); // OK, T = number
box2.getValue().toUpperCase(); // OK, T = string2. A generic class with several parameters
class Pair<K, V> {
constructor(public key: K, public value: V) {}
describe() {
console.log(`Key: ${this.key}, Value: ${this.value}`);
}
}
const pair = new Pair<string, number>("age", 30);
pair.describe(); // Key: age, Value: 30Here
Kis the key type,Vis the value type. You can use any number of generic parameters.
3. A generic class with a constraint (extends)
You can constrain the type parameter so it matches a specific shape:
interface Identifiable {
id: number;
}
class Repository<T extends Identifiable> {
private items: T[] = [];
add(item: T) {
this.items.push(item);
}
findById(id: number): T | undefined {
return this.items.find(i => i.id === id);
}
}
const users = new Repository<{ id: number; name: string }>();
users.add({ id: 1, name: "Tim" });
users.add({ id: 2, name: "Alex" });
console.log(users.findById(2)); // { id: 2, name: 'Alex' }Here
Tmust be an object withid: number. This prevents errors if someone tries to add something without anid.
4. A generic class with a default type
You can set a default type in case none is provided when creating it:
class Storage<T = string> {
private data: T[] = [];
add(item: T) {
this.data.push(item);
}
getAll(): T[] {
return this.data;
}
}
const s1 = new Storage(); // T = string (default)
s1.add("one");
s1.add("two");
const s2 = new Storage<number>();
s2.add(10);
s2.add(20);5. Generic class + interfaces
Interfaces can be generic too, and classes can implement them:
interface IStorage<T> {
add(item: T): void;
getAll(): T[];
}
class ArrayStorage<T> implements IStorage<T> {
private data: T[] = [];
add(item: T) {
this.data.push(item);
}
getAll(): T[] {
return this.data;
}
}This way you can build "type-safe containers".
6. A generic class with inheritance
class BaseResponse<T> {
constructor(public data: T, public success: boolean) {}
}
class ApiResponse<T> extends BaseResponse<T> {
constructor(data: T, public status: number) {
super(data, status >= 200 && status < 300);
}
}
const response = new ApiResponse({ id: 1, name: "Tim" }, 200);
console.log(response.data.name); // TimGenerics can be inherited and passed further down the class hierarchy.
Summary
| Capability | Example | Description |
|---|---|---|
| A simple generic | class Box<T> { ... } | Types the contents |
| Several parameters | class Pair<K, V> | Several types at once |
| A constraint | <T extends SomeType> | Restricts the allowed types |
| A default type | <T = string> | If no type is given |
| Implementing an interface | class A<T> implements I<T> | Together with generic interfaces |
| Inheritance | class B<T> extends A<T> | Generics are passed further |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.