TypeScript · Functions

Generics

Generics let you write one function or type that works with many types while keeping full type safety.

Intermediate 5 min Lesson 14 of 29Examples target TypeScript 5.x with "strict": true.
0/29 in TypeScript
On this page · 5 min · Intermediate

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#

TypeScript Illustrative
function identity<T>(value: T): T { return value; }
interface ApiResponse<T> { data: T; error?: string }

Code example: A typed API response and lookup helper#

TypeScriptA typed API response and lookup helper Illustrative
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);
Expected output
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#

  1. ApiResponse<T> describes any response; ApiResponse<Course[]> fixes T to an array of courses.
  2. findById accepts any array of objects with a numeric id and returns the same element type.
  3. pluck uses K extends keyof T, so only real property names are allowed, and the return type T[K][] follows the chosen key.
  4. 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#

Reaching for any

any switches off type checking. A generic keeps the relationship between input and output types.

Unused type parameters

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
TypeScript Illustrative
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#

Generics quizMultiple choice Question 1 of 1

What does <T extends { id: number }> mean?

Score so far: 0/0

Want more? Practise all TypeScript MCQs · TypeScript interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.