Why does TypeScript infer a literal type for const but a wider type for let?
A const can never change, so its type is the exact value, like "IN". A let can be reassigned, so TypeScript widens it to the general type, string. This is called literal widening and it explains many surprising errors with object properties.
Explain it simply
If you book a Tatkal ticket for seat 23, that seat number is fixed: the type is the literal 23. If you are allowed to change seats later, the best the compiler can say is "some number".
const country = "IN" gets type "IN". let country = "IN" gets type string. Object properties behave like let because they can be changed later, so { mode: "dark" } has mode: string, which can then fail when a function wants "dark" | "light".
Example
const a = "IN"; // type "IN"
let b = "IN"; // type string
type Mode = "dark" | "light";
function setMode(m: Mode) {}
const config = { mode: "dark" }; // mode: string (widened)
// setMode(config.mode); // Error: string not assignable to Mode
const config2 = { mode: "dark" } as const; // mode: "dark"
setMode(config2.mode); // OK
const config3: { mode: Mode } = { mode: "dark" }; // annotation also fixes it
let c: "IN" | "US" = "IN"; // explicit literal union on a letWhat to say in the interview
"TypeScript widens mutable positions, like let and object properties, to the general type, and keeps literals for const. When a literal gets widened and a function wants a union, I fix it with an annotation on the object, or as const to freeze the literals."
Common mistakes
- Thinking const on an object makes its properties literal; only the binding is const.