TypeScript Generics Deep Dive Cheat Sheet
Covers generic functions, constraints with extends and keyof, generic classes with default type parameters, and common generic patterns.
Generic Functions
Write functions that preserve type information across their inputs and outputs.
function identity<T>(value: T): T { return value;}const num = identity<number>(42); // explicit type argumentconst str = identity('hi'); // inferred as stringfunction firstElement<T>(arr: T[]): T | undefined { return arr[0];}// Multiple type parametersfunction pair<A, B>(a: A, b: B): [A, B] { return [a, b];}
Generic Constraints
Restrict a type parameter to shapes that support the operations you need.
interface HasLength { length: number; }function longest<T extends HasLength>(a: T, b: T): T { return a.length >= b.length ? a : b; // T is guaranteed to have .length}longest('abc', 'ab'); // OKlongest([1, 2], [1]); // OK// longest(3, 5); // Error: number has no .length// keyof constraint - safe property accessfunction getProp<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key];}const user = { name: 'Ana', age: 30 };getProp(user, 'name'); // string
Generic Classes & Default Type Parameters
Parameterize an entire class and supply a fallback type.
class Box<T = unknown> { // default type parameter constructor(private value: T) {} get(): T { return this.value; } set(value: T): void { this.value = value; }}const numberBox = new Box<number>(42);const inferredBox = new Box('hello'); // Box<string>class Repository<T extends { id: number }> { private items: T[] = []; add(item: T) { this.items.push(item); } findById(id: number): T | undefined { return this.items.find(i => i.id === id); }}
Common Generic Patterns
Idioms that show up repeatedly in typed codebases.
- T extends U- Constrains T to types assignable to U
- K extends keyof T- Restricts K to be a valid property name of T
- Default type params- <T = DefaultType> supplies a fallback when no argument is given
- Generic interfaces- interface ApiResponse<T> { data: T; error?: string }
- Conditional generics- type NonNull<T> = T extends null | undefined ? never : T
- Generic constraints chaining- <T, K extends keyof T = keyof T> chains constraints between parameters
Building Generic Utility Types
Combine generics with async code for reusable, type-safe wrappers.
type ApiResponse<T> = { data: T; status: number; error?: string;};async function fetchJson<T>(url: string): Promise<ApiResponse<T>> { const res = await fetch(url); const data = await res.json(); return { data, status: res.status };}interface User { id: number; name: string; }const result = await fetchJson<User>('/api/user/1'); // result.data is User
Let TypeScript infer generic type arguments from function arguments whenever possible instead of specifying them explicitly (identity(42) over identity<number>(42)) - explicit annotations should mainly be reserved for cases inference can't determine, like empty arrays.
Explore Topics
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance