What are generics and why are they useful?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Generics parameterize types: <T> lets functions, classes and interfaces work with many types while preserving exact relationships between inputs and outputs. They give reuse without losing inference or safety.
Detailed explanation
Without generics you'd choose between any (no safety) and duplicated overloads per type. Generics let callers decide the type while the definition constrains relationships: function identity<T>(x: T): T guarantees output type equals input type; useState<string> ties the setter to string. Constraints (T extends Shape) require capabilities while keeping specificity: function pluck<T, K extends keyof T>(items: T[], key: K) ensures keys actually exist on T. Multiple parameters express correlations — Map<K, V>, Record<K, V>. Defaults (<T = string>) ease call sites. Generic classes (Repository<T>) and generic constraints on utility types form the backbone of library APIs — React components typed as Props, fetch wrappers returning Promise<T>. The skill interviewers probe: reading unfamiliar generic signatures and knowing when inference removes the need to annotate explicitly.
Example
function groupBy<T, K extends keyof T>(items: T[], key: K) {
return items.reduce<Record<string, T[]>>((acc, item) => {
const group = String(item[key]);
(acc[group] ??= []).push(item);
return acc;
}, {});
}
const users = [{ role: 'admin' }, { role: 'dev' }];
groupBy(users, 'role'); // ✅ key checked against T
groupBy(users, 'age'); // ❌ compile errorInterview tip
Say 'reuse without losing inference' up front, then demo a constrained generic (keyof) — showing the compiler reject a bad key makes generics click.
Common mistakes
- Defaulting to any instead of generics in reusable helpers.
- Not knowing what
extendsconstraints do inside generic clauses.