DEV Community

Safal Bhandari
Safal Bhandari

Posted on

Understanding `readonly` in TypeScript

When working with objects, you sometimes want to prevent accidental changes to certain properties. TypeScript’s readonly modifier helps you lock properties so they can’t be reassigned after creation.

1. The readonly Modifier in Interfaces or Type Aliases

You can add readonly directly to each property:

type User = {
  readonly name: string;
  readonly age: number;
};
Enter fullscreen mode Exit fullscreen mode
  • name and age are both read-only.
  • Once a User object is created, these properties cannot be reassigned.

Example:

const user: User = {
  name: "Safal",
  age: 10,
};

user.age = 12; // ❌ Error: Cannot assign to 'age' because it is a read-only property
Enter fullscreen mode Exit fullscreen mode

TypeScript’s compiler enforces immutability at compile time.
(At runtime, it’s still a normal JavaScript object, but TypeScript stops you from writing code that would mutate it.)


2. Readonly<T> Utility Type

Instead of writing readonly on every property, TypeScript provides a built-in utility type:

type User1 = {
  name: string;
  age: number;
};

const user1: Readonly<User1> = {
  name: "Safal",
  age: 10,
};
Enter fullscreen mode Exit fullscreen mode

Here, Readonly<User1> creates a new type identical to User1, but with all properties marked as readonly.

It’s equivalent to:

type ReadonlyUser1 = {
  readonly name: string;
  readonly age: number;
};
Enter fullscreen mode Exit fullscreen mode

Any attempt to reassign:

user1.name = "New Name"; // ❌ Error: Cannot assign to 'name' because it is a read-only property
Enter fullscreen mode Exit fullscreen mode

3. When to Use readonly

  • Immutable data models: Prevent unintended mutations in configuration objects or Redux state.
  • API boundaries: When exposing data to other parts of the app that should not be modified.
  • Functional programming patterns: Enforce immutability by design.

4. Key Points to Remember

  1. Compile-time only: readonly is enforced by TypeScript’s type checker. JavaScript doesn’t freeze the object automatically.
  • If you need runtime immutability, you can also use Object.freeze().
    1. Shallow: readonly only applies to the top-level properties, not nested objects.

Example:

type Nested = {
  readonly info: { value: number };
};

const x: Nested = { info: { value: 1 } };
x.info.value = 2; // ✅ Allowed, because `value` is not marked readonly
Enter fullscreen mode Exit fullscreen mode

Quick Comparison

Feature Example Effect
Property modifier readonly name: string; Mark individual properties as immutable
Utility type Readonly<User> Make all properties of a type read-only

Summary
Use readonly when you want TypeScript to guarantee immutability of object properties.

  • Add readonly directly to specific properties for fine-grained control.
  • Use the Readonly<T> utility to lock down an entire type at once.

This helps keep your data structures predictable and protects against accidental mutation in large codebases.

Top comments (0)