TypeScript Tutorial · TypeScript Basics · Lesson 6 of 25

TypeScript Readonly and Immutability

readonly properties, ReadonlyArray, as const and Readonly<T>.

readonly everywhere

Immutable data is easier to reason about. TypeScript can enforce it at compile time:

  • readonly on a property.
  • readonly string[] (or ReadonlyArray<string>) — no push, pop or index assignment.
  • Readonly<T> — every property of T becomes readonly (shallow).
  • as const — deeply readonly literals.
Example 1Try it yourself
function total(prices: readonly number[]): number {
  // @ts-expect-error — Property 'push' does not exist on type 'readonly number[]'.
  prices.push(0);
  return prices.reduce((a, b) => a + b, 0);
}

const config = { api: { retries: 3 }, regions: ["eu", "us"] } as const;
// @ts-expect-error — Cannot assign to 'retries' because it is a read-only property.
config.api.retries = 5;

type Point = { x: number; y: number };
const origin: Readonly<Point> = { x: 0, y: 0 };
console.log(total([1, 2, 3]), config.regions, origin);

Output

6 [ 'eu', 'us' ] { x: 0, y: 0 }

These checks exist only at compile time. Use Object.freeze() if you also need runtime protection. Test yourself with the readonly output puzzle.

Test yourself

Does readonly stop changes at runtime?

  1. Yes
  2. No — it is checked only at compile time
Show answer

Answer: No — it is checked only at compile time

Practice next