Syntax
class Name<T> {
value: T;
}Examples
A Generic Stack Class
A reusable data structure that works with any type, chosen when instantiated.
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
}
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 2
const stringStack = new Stack<string>(); // the SAME class, used with a different typeA Generic Interface
A reusable shape for wrapping different kinds of API response data.
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
const userResponse: ApiResponse<{ name: string }> = {
data: { name: "Alice" },
status: 200,
message: "Success"
};
const productsResponse: ApiResponse<string[]> = {
data: ["Laptop", "Mouse"],
status: 200,
message: "Success"
};Best practices
- Use generic classes for reusable data structures (stacks, queues, caches) that should work identically regardless of the specific value type stored
- Use a generic interface like ApiResponse<T> to consistently wrap different data shapes returned from an API, keeping response handling uniform
- Provide the type argument explicitly when constructing a generic class if it cannot be inferred from the constructor arguments, like new Stack<number>()
- Keep a generic class focused on structure and behavior that is genuinely type-independent - if certain methods only make sense for specific types, that is a sign the class may be trying to do too much
Runtime & versions
Compiled to JavaScript. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
TypeScript Handbook