6. Generics
TypeScript · 44 pages source format
Generics are type parameters — reusable functions and types that work across shapes while preserving type relationships. <T> on functions, interfaces, and classes. Constraints with extends. Avoid generic abuse — if T appears once, skip it.
What you'll learn
- Generic functions
- Generic interfaces
- Constraints (extends)
- Default type params
- Generic pitfalls
Generic functions
function first<T>(arr: T[]): T | undefined returns element type matching input. Caller picks T via argument.
function first<T>(arr: T[]): T | undefined {
return arr[0]
}
const n = first([1, 2, 3]) // number | undefined
const s = first(["a", "b"]) // string | undefinedDo this now
Write first, last, and findById<T>(items: T[], id: number, key: keyof T).
Generic interfaces
interface ApiResponse<T> { data: T; status: number; }. Fetch functions return ApiResponse<Post>.
Do this now
Wrap your fetch helpers to return ApiResponse<T>. Type JSONPlaceholder posts and users.
Constraints
function longest<T extends { length: number }>(a: T, b: T): T accesses .length safely.
Do this now
Write sortByKey<T, K extends keyof T>(items: T[], key: K): T[].
Default type parameters
type ApiResult<T = unknown> = ... — fallback when caller omits T.
Do this now
Add default to ApiResponse generic. Use with and without explicit type arg.
When NOT to generic
If function only works with User, type User — do not genericize for vanity. Generics when shape repeats across types.
Do this now
Review your generics. Remove any where T is used only once and never constrained.
Pro tip. Hover generic calls in VS Code — verify T inferred correctly.