A Type-Level Variable
Generics — Intro
A generic is a type variable. It lets one function or type work for many specific types — without losing safety.
What you'll learn
- Recognize generics in built-in types
- Understand why "any" isn't enough
- Read a generic signature
A generic is a type variable. Just like a function takes value parameters, a generic takes a type parameter — you fill it in when you use the function or type.
You’ve Already Seen Them
const tags: Array<string> = ["a", "b"];
const map: Map<string, number> = new Map();
const result: Promise<User> = fetchUser(); Array<T>, Map<K, V>, Promise<T> are all generic types.
You provide the type parameters.
Why Generics Exist
Without them, you’d write any:
function first(arr: any[]): any {
return arr[0];
}
const x = first([1, 2, 3]); // x is any — TS can't help With generics, the return type follows the input type:
function first<T>(arr: T[]): T {
return arr[0];
}
const x = first([1, 2, 3]); // x is number
const y = first(["a", "b"]); // y is string
const z = first([{ id: 1 }]); // z is { id: number } T is a placeholder. TS infers it from the argument; the return
type follows.
Reading a Generic Signature
function map<T, U>(arr: T[], fn: (item: T) => U): U[] {
// ...
} Parse it like this:
<T, U>— two type parametersarr: T[]— array of Tfn: (item: T) => U— function from T to U: U[]— returns array of U
The same shape as Array.map.
How TS Infers Generics
When you call:
map([1, 2, 3], n => `n=${n}`);
// ^ T inferred as number
// ^ U inferred as string
// → returns string[] You almost never have to specify type arguments — TS figures them out from the values.
When To Reach for Generics
- A function whose return type depends on its input type
- A data structure that holds “things of T”
- A utility that works for any type but should keep the type info
If you find yourself typing any to make something compile,
that’s usually the sign you want a generic.
Up Next
Authoring generic functions in detail.
Generic Functions →