← Back to TypeScript Course | Chapter 4: Interfaces | Lesson 3 of 7

Readonly Properties

A readonly property can be assigned when an object is created but cannot normally be changed afterward. This helps protect important values from accidental modification.

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

typescript
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

typescript
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

typescript
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

typescript
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

typescript
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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.