Lesson 35 of 80
as const narrows a literal at the call site — but only if the caller remembers to write it. const on a type parameter moves that narrowing into the function signature itself, guaranteed for every call.
12 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.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →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
The type-inference lesson in this track covers as const: a value like ["loading", "success", "error"] widens to string[] by default, and as const locks it down to the exact literal tuple instead. That works — but it depends on every caller remembering to add as const at every call site. Forget it once, and the narrowing silently disappears for that call.
TypeScript 5.0 added a const modifier for type parameters — <const T> — that moves this responsibility from the caller to the function's own signature. Writing <const T> tells the compiler "always infer the narrowest literal type for T at this call, as if the caller had written as const," without the caller ever needing to write it.
function tuple<T extends readonly unknown[]>(...items: T): T {
return items;
}
const a = tuple("a", "b");
// ^ inferred as string[] — widened, exactly like an ordinary array literal
function constTuple<const T extends readonly unknown[]>(...items: T): T {
return items;
}
const b = constTuple("a", "b");
// ^ inferred as readonly ["a", "b"] — the literal tuple, no as const needed at the call site
Both functions have essentially the same body. The only difference is the const modifier on T's declaration — and that single word changes what every future caller gets by default, permanently, without them doing anything differently.
const type parameters don't make the underlying value more immutable at runtime. Exactly like as const itself, this is a purely type-level narrowing — the array or object passed in is the same plain JavaScript value either way; only TypeScript's inferred type gets more precise.const to your own type parameter instead of relying on every consumer of your function to remember as const themselves.extends constraints. <const T extends string[]> still enforces the constraint — const narrows within whatever the constraint allows, it doesn't loosen or remove the constraint itself.This is a direct extension of the as const idea covered in the type inference lesson elsewhere in this track — being able to explain const type parameters as "moving as const's effect from the call site into the function signature" shows you understand why as const exists in the first place, not just its syntax.