In short
You want one function that works for an array of students, courses or numbers, but still knows exactly what comes out. Generics let your types take a parameter, just like functions do.
Reusable, type-safe functions and components that work across many data types — used constantly for typing API response wrappers, hooks, and reusable UI components.

Think of it like this
The sugarcane juice machine
Same machine, but put in sugarcane and you get sugarcane juice, add ginger and lemon and you get that flavour. The machine doesn't change, the input decides the output. A generic function works the same: whatever type goes in decides the type that comes out.
Watch it happen
How first<T> works out its type
1/4You call first(["DSA", "OS"]). The function is written as first<T>(list: T[]): T | undefined.
The big ideas
What you need to know
<T> is a placeholder
T stands for 'some type, decided later'. It gets filled in when the function is called.
Links input to output
function first<T>(list: T[]): T says 'you get back the same type you put in'.
Usually inferred
Call first([1, 2]) and TypeScript works out T is number. You rarely write it by hand.
Limit with extends
<T extends { id: number }> means T can be anything, as long as it has an id.
See it in code
Walk through the code
1function first<T>(list: T[]): T | undefined {2 return list[0];3}4 5const n = first([10, 20]); // number | undefined6const s = first(["DSA", "OS"]); // string | undefined7 8function findById<T extends { id: number }>(items: T[], id: number) {9 return items.find((item) => item.id === id);10}11 12interface ApiResponse<T> {13 data: T;14 error: string | null;15}16const res: ApiResponse<string[]> = { data: ["BCA"], error: null };1/4T is a placeholder. Whatever the array holds, the result is that same type, or undefined.
findById works for students, courses or anything with an id, and still returns the exact type you passed in.
Save yourself the pain
Common mistakes
Oops
Writing (list: any[]): any and losing the type of what comes out.
Do this instead
Use a generic <T> so the return type matches the input.
Oops
Adding generics where a simple type would do.
Do this instead
If the type never changes, skip the generic. Use one when the input type should flow into the output.
Your mission
Write your own generic helpers
Quick check
const x = first([true, false]); with first<T>(list: T[]): T | undefined. What's the type of x?
Go deeper
- 1Write a generic `ApiResponse<T>` type wrapping your API's success/error responses.
- 2Build a generic `useFetch<T>` hook that returns typed data.
- 3Learn generic constraints to restrict what types are allowed.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.