When an interviewer asks about TypeScript generics, they’re looking for three things: you understand the why (reusability and safety), the how (type parameters and inference), and the implications (complexity, readability, and tooling). Below is a roadmap you can follow in an interview, plus a concrete example and a 60‑second spoken version you can rehearse with Call Assistant.
Why Generics Matter
- Reusability – Write one function or class that works for many shapes instead of duplicating code for each concrete type.
- Type safety – The compiler can catch mismatches that would otherwise be runtime errors.
- Documentation – The generic signature reads like a contract: "this works for any
Tthat satisfies these constraints."
In most interview loops, candidates who can articulate these benefits quickly earn extra credibility.
How Generics Work
TypeScript introduces type parameters inside angle brackets (<T>). At the call site, the compiler either infers the concrete type or you supply it explicitly.
function identity<T>(value: T): T {
return value;
}
const num = identity(42); // T is inferred as number
const str = identity<string>('hi'); // explicit generic argument
The function body sees value as a generic placeholder T. The return type is guaranteed to be the same type, so the compiler enforces consistency.
Constraints
Sometimes you need to restrict T to types that have certain properties. Use the extends clause:
function getId<T extends { id: string }>(obj: T): string {
return obj.id;
}
Now T must have an id property, letting the function safely read it.
Trade‑offs and Gotchas
| Aspect | Benefit | Cost |
|---|---|---|
| Readability | Concise, expressive signatures | New developers may need to learn the syntax |
| Inference | Often automatic, no need to specify <T> | Complex unions can confuse the compiler, requiring manual annotation |
| Error messages | Precise, point to exact mismatches | Can become verbose when constraints are deep |
| Performance | No runtime impact (erased at compile time) | Slight compile‑time overhead for large generic hierarchies |
In practice, you balance the elegance of a generic API against the mental load for the code reviewer. If a generic makes the implementation obscure, a concrete overload may be preferable.
Typical Interview Questions
- “What are generics, in one sentence?” – Answer: “Generics let you write a component that works with any type while preserving type safety.”
- “How does TypeScript infer the type argument?” – It looks at the arguments you pass to a generic function and picks the most specific type that satisfies the constraints.
- “When would you use a generic constraint versus overloads?” – Use constraints when you need to guarantee a property exists across many types; overloads are better when the return shape diverges significantly.
- “Can you give an example of a generic class?” – A
Stack<T>that stores items of any type, withpush,pop, andpeekmethods. - “What are the limits of inference?” – In cases like
function foo<T>(arg: T[]): T { … }, callingfoo([])yieldsany[]because the empty array provides no clues, so you may need to annotate the type explicitly.
A Concrete Example to Discuss
Imagine you’re building a small in‑memory cache that can store any kind of value keyed by a string. A generic class makes the API clean:
class SimpleCache<T> {
private store = new Map<string, T>();
set(key: string, value: T): void {
this.store.set(key, value);
}
get(key: string): T | undefined {
return this.store.get(key);
}
}
// Usage
const userCache = new SimpleCache<{ name: string; age: number }>();
userCache.set('alice', { name: 'Alice', age: 30 });
const alice = userCache.get('alice'); // inferred as { name: string; age: number } | undefined
Key points to highlight:
- The class is reusable for any payload shape.
- The compiler guarantees that
setreceives the same type thatgetreturns. - If you tried to store a
numberinuserCache, TypeScript would flag it.
60‑Second Spoken Answer
“Generics are a way to write functions, classes, or interfaces that work with any type while still keeping the compiler happy. You declare a type variable inside angle brackets—
<T>—and then use that variable in the signature. At the call site, TypeScript either infers the concrete type from the arguments or you supply it explicitly. For example,function identity<T>(x: T): T { return x; }works for numbers, strings, or any object, and the compiler ensures the return matches the input type. You can also add constraints withextendsso thatTmust have certain properties, likefunction getId<T extends { id: string }>(obj: T). The trade‑offs are that generics add a bit of mental overhead and sometimes inference can be ambiguous, but they dramatically reduce duplicated code and prevent a class of runtime bugs. In an interview, I’d illustrate this with a genericCache<T>class that stores any payload type, showing how the type safety flows fromsettoget.”
You can rehearse this answer aloud and get instant feedback on pacing with Call Assistant, which will keep the follow‑up questions aligned with the topic.
How to Practice This
- Write a tiny generic utility – Pick a common pattern (e.g.,
map,filter, or a simple cache) and implement it in a fresh TypeScript file. Observe how the compiler infers types. - Record yourself – Use Call Assistant to read the 60‑second answer aloud. Listen for filler words and adjust to stay within the time limit.
- Mock interview – Pair with a peer and ask each other the typical questions listed above. Focus on explaining the why before the how and keep examples concrete.
FAQ
- What is the difference between a generic type and the
anytype? A generic type preserves the relationship between input and output types, whileanydisables type checking entirely, losing safety. - When should I avoid using generics? If the added abstraction makes the code harder to read for the intended audience, or if the function only ever handles a small set of known types, concrete overloads may be clearer.
- Do generics affect runtime performance? No. TypeScript erases generics during compilation, so the generated JavaScript contains no generic metadata.
- Can I nest generics?
Yes. For example,
Promise<Array<T>>is a common nested generic, and the compiler can inferTthrough multiple layers of type arguments.
Frequently asked questions
What is the difference between a generic type and the any type?
A generic type keeps the relationship between input and output types, allowing the compiler to enforce consistency, whereas `any` turns off type checking and provides no safety guarantees.
When should I avoid using generics?
If the abstraction makes the code harder to understand for the team, or if the function only ever needs a few concrete types, explicit overloads can be clearer than a generic.
Do generics affect runtime performance?
No. Generics are a compile‑time construct; they are stripped out when TypeScript emits JavaScript, so there is no runtime overhead.
Can I nest generics in TypeScript?
Yes. Types like `Promise<Array<T>>` or `Map<string, Set<T>>` are common, and the compiler can infer the inner type argument through multiple layers.
#concept#TypeScript generics#interview#coding#typescript