Generics
Part of the Backend Developer Roadmap
In short
Every API response has the same wrapper but different data inside. Generics let you write that wrapper once and still keep exact types for users, orders or anything else.
Reusable, type-safe functions and classes that work across many data types — commonly used for typing API response wrappers and repository/service patterns.

Think of it like this
Identical clear containers
Your mother's kitchen has identical clear containers. One holds rice, one biscuits, one your marbles. The box is the same design, but you always know what's inside. A generic like Box<T> is that container: same shape, any content, clearly known.
Watch it happen
One wrapper, many contents
1/4ApiResponse<T> has ok, data: T and an optional error. T is a placeholder for the content type.
The big ideas
What you need to know
T is a type variable
Like a function parameter, but for types. The caller decides what T is, or TypeScript infers it.
Write once, stay typed
One generic function replaces many copies, and you don't lose type safety like you would with any.
Constrain with extends
<T extends { id: string }> means T can be anything, as long as it has an id.
You already use them
Array<string>, Promise<User> and Record<string, number> are all generics.
See it in code
Walk through the code
1type ApiResponse<T> = {2 ok: boolean;3 data: T;4 error?: string;5};6 7function success<T>(data: T): ApiResponse<T> {8 return { ok: true, data };9}10 11function findById<T extends { id: string }>(items: T[], id: string): T | undefined {12 return items.find((item) => item.id === id);13}14 15const res = success({ id: "u1", email: "a@x.in" });16res.data.email; // typed as string, no casting needed1/4A generic response type. T stands for whatever data this response carries.
You never wrote success<User>. TypeScript looked at the argument and inferred T for you.
Save yourself the pain
Common mistakes
Oops
Writing getUserResponse, getOrderResponse and getCartResponse types separately.
Do this instead
Write one ApiResponse<T> and plug in User, Order or Cart.
Oops
Using <T> where it isn't needed, like function log<T>(msg: T) that just prints.
Do this instead
Use a generic only when it connects types, like input to output. Otherwise a normal type is clearer.
Your mission
A typed repository
Quick check
What does <T extends { id: string }> mean?
Go deeper
- 1Write a generic `ApiResponse<T>` type wrapping your API's success/error responses.
- 2Build a generic repository function that fetches typed data from a database.
- 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.