Mutability Limits

Enforcing immutability with readonly and 'as const'.

TypeScript5 min readConcept 35 of 54

Preventing Accidental Mutation

In JavaScript, const only prevents variable reassignment; it does not prevent you from mutating the properties of an object or pushing to an array.

TypeScript adds the readonly modifier and the as const assertion to enforce true deep immutability at compile-time.

Literal Widening

If you declare const method = "GET", TypeScript knows it's the literal type "GET". But if you declare const obj = { method: "GET" }, TypeScript assumes you might change it later, so it widens the type to string.

If you pass that object to fetch(url, { method: obj.method }), TypeScript will complain that string is not assignable to "GET" | "POST". Using as const prevents this widening.

Syntax

typescript // 1. The readonly modifier (surface level) type User = { readonly id: number; name: string }; const u: User = { id: 1, name: "Alice" }; u.id = 2; // Error: Cannot assign to 'id' because it is a read-only property. // 2. The as const assertion (deep freeze) const config = { endpoint: "/api", retries: 3 } as const; config.retries = 4; // Error // config is now exactly: // { readonly endpoint: "/api"; readonly retries: 3; }

Try it

Toggle the as const assertion on the configuration object and watch how it restricts property mutation by turning the wide string type into a strict readonly "GET" literal.

const config = {
method: "GET"
}
+ add assertion
;

// Attempting Mutation
config.method = "POST";
Type Inference
Inferred typeof config
{
readonlymethod:
string"GET"
}
Mutation Result
Mutation Succeeded

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What is the difference between `const x = { a: 1 }` and `const y = { a: 1 } as const`?

Remember this

  • const prevents variable reassignment; it does NOT make objects immutable.
  • readonly prevents a specific property from being mutated.
  • as const freezes an entire object or array deeply, inferring literal types instead of wide types.
  • Mutable arrays can be assigned to readonly arrays, but not vice-versa.

Done with this concept?

Mark it complete to track your progress. No login needed.