Mutability Limits
Enforcing immutability with readonly and 'as const'.
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.
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
constprevents variable reassignment; it does NOT make objects immutable.readonlyprevents a specific property from being mutated.as constfreezes 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.