Generics
Generics let you write one function or type that works with many types while keeping full type safety.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 1, 2026
Related tutorials
Learning objectives#
- Write a generic function with a type parameter
- Constrain type parameters with extends
- Define generic interfaces such as ApiResponse<T>
- Use keyof in generic constraints
Explanation#
A type parameter, written <T>, is a placeholder for a type supplied when the function is used. TypeScript usually infers it from the arguments.
Without generics you would either duplicate code for each type or fall back to any, losing type checking.
extends adds a constraint: <T extends { id: number }> accepts any type that has a numeric id.
Syntax#
function identity<T>(value: T): T { return value; }
interface ApiResponse<T> { data: T; error?: string }
Code example: A typed API response and lookup helper#
interface ApiResponse<T> {
data: T;
error?: string;
}
interface Course { id: number; title: string }
function findById<T extends { id: number }>(items: T[], id: number): T | undefined {
return items.find(item => item.id === id);
}
function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
return items.map(item => item[key]);
}
const res: ApiResponse<Course[]> = {
data: [{ id: 1, title: 'React' }, { id: 2, title: 'Angular' }],
};
const course = findById(res.data, 2); // Course | undefined
const titles = pluck(res.data, 'title'); // string[]
// pluck(res.data, 'price'); // ✗ Error: '"price"' is not assignable to '"id" | "title"'
console.log(course?.title, titles);
Angular [ 'React', 'Angular' ]
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- ApiResponse<T> describes any response; ApiResponse<Course[]> fixes T to an array of courses.
- findById accepts any array of objects with a numeric id and returns the same element type.
- pluck uses K extends keyof T, so only real property names are allowed, and the return type T[K][] follows the chosen key.
- Passing an unknown key is a compile-time error — the bug never reaches the browser.
Real-world use case#
Typed HTTP clients (http.get<User[]>()), React state (useState<User | null>(null)), repositories and utility libraries all rely on generics.
Common mistakes#
any switches off type checking. A generic keeps the relationship between input and output types.
If T appears only once in a signature, it is probably not needed.
Best practices#
- Let TypeScript infer type arguments where possible
- Constrain generics with extends instead of casting
- Use descriptive names (TItem, TKey) in complex signatures
- Keep generic signatures as simple as possible
Remember this#
<T> is a placeholder for a type.
Generics keep type safety without repeating code.
Constrain with <T extends Something>.
Practice exercise#
Your task: Write a generic function last<T>(items: T[]): T | undefined that returns the final element.
Show solution
function last<T>(items: T[]): T | undefined {
return items[items.length - 1];
}
const n = last([1, 2, 3]); // number | undefined
const s = last(['a', 'b']); // string | undefined
Mini quiz#
What does <T extends { id: number }> mean?
Want more? Practise all TypeScript MCQs · TypeScript interview questions
My notes#
Saved in this browser.