Lesson 4 of 80
A generic is a placeholder for a type, filled in at the call site — the same instinct as a function parameter, one level up.
14 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
function identity<T>(x: T): T and function identityAny(x: any): any both 'accept anything.' What's the actual difference in what TypeScript knows afterward?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A function parameter is a placeholder for a value, filled in when the function is called. A generic is a placeholder for a type, filled in the same way — at the call site, not when the function is defined.
function identity<T>(x: T): T {
return x;
}
T isn't a real type — it's a stand-in. identity(42) fills T with number; identity("hi") fills it with string. Each call gets its own, independently correct substitution.
any throws awayfunction identityAny(x: any): any {
return x;
}
const a = identityAny(42); // a: any — TypeScript forgot it was a number
const b = identity(42); // b: number — TypeScript remembers
Both functions "accept anything." Only one of them keeps track of what it accepted. any isn't a permissive generic — it's the total absence of type checking, and that absence propagates: a.toFixed(2) type-checks even if a turns out to be a string at runtime, because TypeScript gave up tracking it entirely the moment it became any.
function identity<T>(x: T): T — T is a placeholder for a type, filled in wherever this function is actually called.
any gives up that relationship completely.function merge<T, U>(a: T, b: U): T & U combines two independently-typed inputs into one intersection type, still fully tracked.<T extends { id: string }> still lets T be any shape with at least an id: string — the function just isn't allowed to assume anything more than that about it.<List<T> items={T[]} renderItem={(item: T) => ...} /> types itself differently depending on what data it's actually given — the same generic-function idea, applied to JSX."What's the difference between generics and any?" is a favorite because a shallow answer ("they both accept anything") misses the entire reason generics exist — to keep the compiler's understanding of your code intact across a function boundary, instead of throwing it away at the first sign of flexibility.