What are generics in TypeScript?

TypeScript

The short answer

Generics let you write functions, types, and components that work over a type you supply later, while preserving that type instead of falling back to any. A generic is a type level parameter: you name a placeholder like T, and TypeScript fills it in based on how the code is called. This is how you build reusable utilities that stay type safe.

A generic function

function identity<T>(value: T): T {
return value;
}
const a = identity('hello'); // a is "hello"
const b = identity(42); // b is 42

The return type tracks the argument. identity('hello') returns the literal type "hello", not any, so you keep autocomplete and type checking afterward. With let, TypeScript widens the result to string.

Constraints with extends

Sometimes a generic should not accept literally any type. extends limits which types are allowed while still preserving the specific one passed in:

function longest<T extends { length: number }>(
a: T,
b: T
): T {
return a.length >= b.length ? a : b;
}
longest('abc', 'de'); // ok, strings have length
longest([1, 2], [3]); // ok, arrays have length
longest(1, 2); // Error: number has no length

A constraint can also be a union. To scope a generic to string | number, write B extends string | number. Without the constraint, any type is allowed, including boolean:

type FooFunc = <B>(bar: B) => B;
const f: FooFunc = (bar) => bar;
f(true); // ok, returns true

With the constraint, B must be assignable to string | number, and the function still returns the specific type passed in:

type FooFunc = <B extends string | number>(bar: B) => B;
const f: FooFunc = (bar) => bar;
f('hello'); // ok, returns "hello"
f(123); // ok, returns 123
f(true); // Error: boolean is not assignable
// to string | number

Default type parameters

You can give a generic a fallback so callers do not always have to specify it:

interface ApiResponse<T = unknown> {
data: T;
status: number;
}
const a: ApiResponse = { data: 'anything', status: 200 }; // T is unknown
const b: ApiResponse<number[]> = {
data: [1, 2],
status: 200,
};

Generic components and hooks

Generics shine in React utilities that should work with any item type:

function useList<T>(initial: T[]) {
const [items, setItems] = useState<T[]>(initial);
const add = (item: T) =>
setItems((prev) => [...prev, item]);
return { items, add };
}
const { items, add } = useList<string>([]);
add('first'); // only strings are accepted

Interview Tip

Once a signature has more than one type parameter, name them for what they are: TItem, TKey, TResult read far better than T, U, V. Also be ready to explain the difference between a generic and any: both accept many types, but a generic remembers which one it received, so the result stays typed. any forgets, and type safety is lost from that point on.

Why interviewers ask this

Generics separate intermediate TypeScript from beginner TypeScript. They show up whenever you build something reusable: a data fetching hook, a table component, a cache, a utility function. Interviewers want to see that you can keep a value's specific type flowing through a reusable abstraction, and that you constrain the generic when the code needs certain properties to exist.