Const Assertions (as const)
Const Assertions (as const)
Level 11 — Modules, Declaration Files & Configuration A powerful TypeScript feature that locks down the types of arrays and objects, converting them into deeply immutable, perfectly literal types.
1. Prerequisites
- Literal Types — The specific, exact types that
as constgenerates. - Enums — The legacy feature that
as constis rapidly replacing.
2. Term Category
Type System Fundamental (Deep Immutability & Literal Casting): Const assertions (as const) construct deeply readonly object structures and infer literal primitive types without widening.
3. Explanation
4. Common Mistakes & Pitfalls
Mistake 1: Expecting as const to Provide Runtime Protection
const config = { host: "localhost" } as const;
// ❌ INCORRECT: Expecting as const to execute Object.freeze() at runtime
// (config as any).host = "other"; // Mutates runtime object!
Why it's wrong: as const is a compile-time type assertion; it is erased completely in transpiled JavaScript output and does NOT perform Object.freeze() at runtime.
Golden Rule: Use as const for compile-time type locking and Object.freeze() if runtime immutability is required.
Mistake 2: Applying as const to Variables Instead of Expressions
// ❌ INCORRECT: Applying as const to variable declaration
// const x as const = "hello"; // Syntax Error!
// ✅ CORRECT (Apply to expression value):
const x = "hello" as const;
Why it's wrong: as const is a type assertion applied to value expressions, not a variable declaration keyword.
Golden Rule: Place as const after the value expression (value as const).
Mistake 3: Confusing Array as const with Regular Arrays
const tuple = [1, 2] as const;
// ❌ INCORRECT: Attempting to push to a const tuple
// tuple.push(3); // Compile Error: Property 'push' does not exist on type 'readonly [1, 2]'.
Why it's wrong: as const on array literals infers readonly fixed-length tuples, stripping array mutation methods like push.
Golden Rule: Remember that as const arrays become immutable readonly tuples.
5. Practice Exercises
Exercise 1: Locking Objects into Readonly Literals with as const
Scenario:
Create an immutable configuration object using as const to prevent property mutation and widening.
Requirements:
- Apply
as constto configuration object.
Answer
Implementation
const appConfig = {
endpoint: "https://api.example.com",
timeout: 5000,
allowedRoles: ["admin", "editor"]
} as const;
// appConfig.timeout = 10000; // ❌ Compile Error: Cannot assign to read-only property!
// appConfig.allowedRoles.push("user"); // ❌ Compile Error: Property 'push' does not exist on readonly tuple!
Technical Explanation
as constlocks all object fields into deeplyreadonlyproperties.- Prevents string and number literal widening (
"https://..."is inferred as exact literal type, notstring). - Converts array literals (
["admin", "editor"]) into fixedreadonlytuples.
Exercise 2: Generating Union Types from as const Arrays
Scenario:
Extract a string literal union type from a const array of navigation routes.
Requirements:
- Define
const ROUTES = ["/home", "/about", "/contact"] as const. - Extract
type Route = (typeof ROUTES)[number].
Answer
Implementation
const ROUTES = ["/home", "/about", "/contact"] as const;
type Route = (typeof ROUTES)[number];
// Inferred as: "/home" | "/about" | "/contact"
function navigateTo(route: Route) {
console.log(`Navigating to ${route}`);
}
navigateTo("/home");
// navigateTo("/dashboard"); // ❌ Compile Error!
Technical Explanation
as constpreserves exact string literal array element types (readonly ["/home", ...]).(typeof ROUTES)[number]extracts a string literal union of all array elements.- Standard pattern for creating runtime array constants and compile-time union types simultaneously.
Exercise 3: Auditing as const vs Object.freeze()
Scenario:
Formulate an architectural comparison matrix contrasting as const against Object.freeze().
Requirements:
- Contrast compilation stage, deep immutability, and runtime bundle footprint.
Answer
Implementation
as const vs Object.freeze() Matrix:
- as const: Compile-time ONLY (0 bytes in JS output). Deeply freezes all nested properties and array tuples statically.
- Object.freeze(): Runtime JavaScript execution. Shallow immutability (nested properties can still be mutated at runtime).
Technical Explanation
as constprovides deep compile-time type safety without runtime execution overhead.Object.freeze()is a shallow runtime JavaScript function call.- Combine
Object.freeze(obj as const)for both compile-time and runtime immutability.
6. Related Terms
- Type Assertions (
as) —as constis a specialized form of the standardas Typesyntax.
7. Key Takeaways
as constconstructs deeplyreadonlyobject structures and array tuples.- Prevents string and number literal type widening at compile time.
(typeof ARRAY)[number]extracts string literal union types fromas constarrays.- Pure compile-time type assertion with zero runtime JavaScript output.