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
At a glance
- Purpose
- Static types for JavaScript
- File extension
- .ts ยท .tsx
- Runs in
- Compiled to JavaScript
- Usually used with
- JavaScript and its ecosystem
Specifications & further reading
Related TypeScript documentation
Generics Basics
Generics let you write reusable functions, classes, and types that work with a variety of types while still preserving type safety - rather than using any and losing that safety, or writing near-duplicate code for each type. A generic type parameter, conventionally named T, acts as a placeholder that gets filled in with a real type each time it is used.Generic Constraints
By default, a generic type parameter can be anything. The extends keyword constrains it to only types compatible with a given shape, letting you safely access specific properties or methods within the generic function while still supporting many different concrete types.Conditional Types
A conditional type selects between two types based on a condition, using syntax that mirrors JavaScript's ternary operator: T extends U ? X : Y. This lets you build types that adapt based on the shape of another type, forming the foundation for many of TypeScript's built-in utility types.The infer Keyword
infer, used only within the extends clause of a conditional type, lets you declare a new type variable that captures part of a matched structure, so it can be reused in the result. It is the mechanism behind utility types like ReturnType<T> and Parameters<T>, which extract specific pieces of a function's type signature.
Generics let you write reusable functions, classes, and types that work with a variety of types while still preserving type safety - rather than using any and losing that safety, or writing near-duplicate code for each type. A generic type parameter, conventionally named T, acts as a placeholder that gets filled in with a real type each time it is used.Generic Constraints
By default, a generic type parameter can be anything. The extends keyword constrains it to only types compatible with a given shape, letting you safely access specific properties or methods within the generic function while still supporting many different concrete types.Conditional Types
A conditional type selects between two types based on a condition, using syntax that mirrors JavaScript's ternary operator: T extends U ? X : Y. This lets you build types that adapt based on the shape of another type, forming the foundation for many of TypeScript's built-in utility types.The infer Keyword
infer, used only within the extends clause of a conditional type, lets you declare a new type variable that captures part of a matched structure, so it can be reused in the result. It is the mechanism behind utility types like ReturnType<T> and Parameters<T>, which extract specific pieces of a function's type signature.