TS Readonly
The readonly modifier marks a property as set-once. TypeScript checks at compile time — JavaScript doesn't enforce it at runtime, but it catches plenty of bugs before they ship.
On a class field
TS
class Money {
constructor(public readonly cents: number) {}
}
const m = new Money(1000);
// m.cents = 2000; // ✗ Cannot assign to 'cents' because it is read-only.
On an interface / type alias
TS
interface Config {
readonly host: string;
readonly port: number;
}
const c: Config = { host: 'localhost', port: 5432 };
// c.host = 'other'; // ✗ error
ReadonlyArray and readonly tuple
TS
const days: readonly string[] = ['Mon', 'Tue'];
// days.push('Wed'); // ✗ error — no push on ReadonlyArray
const rgb: readonly [number, number, number] = [255, 128, 0];
// rgb[0] = 0; // ✗ error
Readonly utility type
TS
type Config = { host: string; port: number };
type FrozenConfig = Readonly<Config>;
// equivalent to: { readonly host: string; readonly port: number }
"as const" makes things deeply readonly
TS
const STATUSES = ['paid', 'pending'] as const; // type: readonly ['paid', 'pending'] // STATUSES[0] = 'oops'; // ✗
readonly vs const
const | readonly |
|---|---|
| Variable binding doesn't change. | Property of an object doesn't change. |
| Statement-level. | Class / interface member. |
| JS construct. | TS-only modifier. |
Tip:
readonly is shallow — readonly users: User[] stops you reassigning the array but not mutating it. Use readonly User[] (note: outside the brackets) to make the array itself immutable too.Example
Example
interface Config {
readonly host: string;
readonly port: number;
}
const cfg: Config = { host: 'localhost', port: 5432 };
// cfg.host = 'other'; // ✗ error
console.log(cfg);
Try it Yourself »
Exercise
Make every property of T readonly.
type Frozen =
<T>;
PascalCase; eight chars.
Discussion
Loading…