Generics basics
📚 What are Generics in TypeScript? Generics are 'type parameters' -- they let you write code that works with ANY type while still being type-safe. Instead of writing a separate function for numbers and a separate one for strings, you write one generic function and TypeScript figures out (or you te…

Appy Says…
What if you want a function that works with arrays of strings AND arrays of numbers, but returns the right type in each case? Generics are TypeScript's way of writing code that's type-safe AND reusable across many types.
What are TypeScript Generics?
Generics let you write functions, classes, and interfaces that work with a variety of types while still maintaining type safety. Think of T as a placeholder for a type that gets filled in when you use the function.
- •Syntax:
function identity<T>(value: T): T { return value; } - •Use:
identity<string>('hello')or let TS infer:identity(42) - •Array generic:
function first<T>(arr: T[]): T { return arr[0]; } - •Constrain:
<T extends object>— T must be an object - •Multiple:
<T, K extends keyof T> - •Built-in generics:
Array<T>,Promise<T>,Record<K, V>
Think of it like a Minecraft container that holds any item type
A shulker box can hold any type of item — swords, food, blocks. Generics are a shulker box for types. Define the box once, use it for any item type, and TypeScript knows exactly what type comes out when you access it.
How It Works
- •1. Add
<T>after the function name to declare a type parameter - •2. Use
Tas a type annotation inside the function - •3. When called, TypeScript infers
Tfrom the argument or you can specify it explicitly - •4. Constraints:
<T extends string>means T must be assignable to string - •5. Generic interfaces:
interface Wrapper<T> { value: T; label: string; } - •6.
keyof:<K extends keyof T>— K must be a key of T
Real-World Examples
- •
function last<T>(arr: T[]): T | undefined { return arr[arr.length - 1]; } - •
interface ApiResponse<T> { data: T; error: string | null; status: number; } - •React:
useState<User | null>(null) - •fetch wrapper:
async function fetchJSON<T>(url: string): Promise<T> { ... }
Key Facts
- •Generics are erased at runtime — they're purely a compile-time construct
- •React's own hooks use generics:
useState<T>,useRef<T> - •The convention is single uppercase letters:
T(type),K(key),V(value),E(element) - •Conditional types and mapped types are advanced generic features used in utility types like
Partial<T>
Watch Out!
Don't over-use generics. If a function only ever works with strings, just type it as string. Generics add complexity — use them only when the function genuinely needs to work across multiple types while preserving type relationships.
Remember
function fn<T>(x: T): T — T is inferred from the argument. Use generics when you need a function/interface that works across types while maintaining the type relationship.
What You Learned
- •Generics: type parameters (
) make functions/interfaces reusable across types - •TypeScript infers T from usage; constraints with extends limit what T can be
- •Unlocks: typed API wrappers, reusable data structures, typed React hooks
Key Facts
- →Generics are erased at runtime — they're purely a compile-time construct
- →React's own hooks use generics:
useState<T>,useRef<T> - →The convention is single uppercase letters:
T(type),K(key),V(value),E(element) - →Conditional types and mapped types are advanced generic features used in utility types like
Partial<T>
Real-World Examples
Remember
function fn<T>(x: T): T — T is inferred from the argument. Use generics when you need a function/interface that works across types while maintaining the type relationship.
Quick Quiz
Generic T stands for?