Readonly Properties
In this page:
Declaring Readonly Properties
Placing readonly before a property inside an interface, like readonly id: number, prevents that property from being directly reassigned after the object is created. Any attempt to write to it outside of the object's initial creation produces a compile-time error.
Example: Declaring Readonly Properties
interface Item {
readonly id: number;
name: string;
}
const item: Item = { id: 1, name: "Widget" };
// item.id = 2; // rejected: id is readonly
console.log(item);
Readonly and Object Creation
Readonly properties receive their initial value at the moment the object is created and are expected to stay fixed from then on. This is ideal for values like a database ID or a creation timestamp that should never legitimately change during the object's lifetime.
Example: Readonly and Object Creation
interface Record {
readonly createdAt: string;
}
const record: Record = { createdAt: "2024-01-01" };
console.log(record.createdAt);
Readonly Arrays
A readonly array type, written as readonly number[], prevents any mutating method like push, pop, or splice from being called on it, and blocks direct index assignment too. It's a compile-time guarantee that a given array reference won't be modified through that variable.
Example: Readonly Arrays
const ids: readonly number[] = [1, 2, 3];
// ids.push(4); // rejected: readonly arrays block mutation
console.log(ids);
Readonly Does Not Mean Deeply Immutable
It's important to know that readonly only protects the property it's applied to directly; if that property holds a nested object, the nested object's own properties are not automatically made immutable. Deep immutability requires applying readonly recursively or using a dedicated utility type.
Example: Readonly Does Not Mean Deeply Immutable
interface Wrapper {
readonly data: { count: number };
}
const wrapper: Wrapper = { data: { count: 1 } };
wrapper.data.count = 99; // allowed: nested object isn't protected
console.log(wrapper.data.count);
Readonly with Functions
Readonly properties are especially useful for functions that need to read important values without accidentally changing them, such as a function that reports on an object's state without being allowed to mutate it. This turns an easy-to-miss bug into a compiler error instead.
Example: Readonly with Functions
interface Point {
readonly x: number;
readonly y: number;
}
function report(point: Point): string {
return `(${point.x}, ${point.y})`;
}
console.log(report({ x: 3, y: 4 }));
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: