Operators
as const
Stops the compiler widening a literal to its general type.
What it is
By default `const x = 1` is `1` but `{ a: 1 }` has `a: number`, because object properties are mutable and a mutable slot cannot promise to stay `1`. `as const` says nothing here will be reassigned, so the literal types can be kept and arrays become readonly tuples. It is the entry point to almost every type-level trick that starts from real data.
Examples
typeof plain→{ kind: string; sides: number; }typeof frozen→{ readonly kind: "circle"; readonly sides: 0; }Every property becomes `readonly` and every value keeps its literal type.
typeof tuple→readonly [1, 2]An array becomes a readonly tuple, which is how a literal array reaches the type level with its length intact.
Each resolved type above was printed by TypeScript 5.9.3, not written by hand.
What it does not do
- It does not freeze anything at run time. `Object.freeze` does that; `as const` is erased and the object is as mutable as it ever was.
- It does not go through function calls. `as const` applies to the literal you wrote, not to whatever a function returns.
Takeaway
If a type-level trick "does not work on my data", check whether the data widened. `as const` is the answer surprisingly often.