What are generics in TypeScript?
TypeScriptThe 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 42The 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 lengthlongest([1, 2], [3]); // ok, arrays have lengthlongest(1, 2); // Error: number has no lengthA 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 trueWith 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 123f(true); // Error: boolean is not assignable// to string | numberDefault 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 unknownconst 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 acceptedInterview 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.