How to make object properties read-only or immutable in TypeScript?

January 7, 2022 - 4 min read

To make an object property read-only or immutable, you can use the readonly keyword before the property name in the type declaration for the object in TypeScript.

TL;DR

// Object type declaration
// where the name property is read-only
interface PersonDetails {
  readonly name: string;
  age: number;
}

// make a new object that
// satisfies the PersonDetails interface
const johnDetails: PersonDetails = {
  name: "John Doe",
  age: 23,
};

// try to assign a new value to
// the read-only `name` property
// in the `johnDetails` object
johnDetails.name = "Lily John"; // ❌ Error. Cannot assign to 'name' because it is a read-only property.

For example, let's say we need to make an object to store a person's details where it needs to have 2 properties called name and age.

So first let's make an interface called PersonDetails and write the property names and the types it should hold.

It can be done like this,

// Object type declaration
interface PersonDetails {
  name: string;
  age: number;
}

Now we need to make the name property read-only or immutable, to do that we can use the readonly keyword before the property name in the PersonDetails interface type declaration.

It can be done like this,

// Object type declaration
// where the name property is read-only
interface PersonDetails {
  readonly name: string;
  age: number;
}

After making the name property as readonly, let's now make an object called johnDetails and use the PersonDetails interface as its type like this,

// Object type declaration
// where the name property is read-only
interface PersonDetails {
  readonly name: string;
  age: number;
}

// make a new object that
// satisfies the PersonDetails interface
const johnDetails: PersonDetails = {
  name: "John Doe",
  age: 23,
};

Now that we have made the object, let's try to assign a new value to the read-only name property in the johnDetails object.

It can be done like this,

// Object type declaration
// where the name property is read-only
interface PersonDetails {
  readonly name: string;
  age: number;
}

// make a new object that
// satisfies the PersonDetails interface
const johnDetails: PersonDetails = {
  name: "John Doe",
  age: 23,
};

// try to assign a new value to
// the read-only `name` property
// in the `johnDetails` object
johnDetails.name = "Lily John"; // ❌ Error. Cannot assign to 'name' because it is a read-only property.

As you can see the TypeScript compiler doesn't allow assigning a new value to the read-only property name and also shows us an error saying Cannot assign to 'name' because it is a read-only property which is exactly what we want to happen.

We have successfully made the object property read-only or immutable. Yay 🥳!

See the above code live in codesandbox.

CAVEAT

If you have a nested object for the read-only object property, TypeScript doesn't show us an error when changing the object properties values inside the nested object.

TypeScript will only show the error if you are changing the value for the read-only object property itself.

For example, this is a valid code in TypeScript even though the otherDetails property is a readonly property.

// Object type declaration
// where the name and the otherDetails
// properties are read-only
interface PersonDetails {
  readonly name: string;
  age: number;
  readonly otherDetails: { salary: number };
}

// make a new object that
// satisfies the PersonDetails interface
const johnDetails: PersonDetails = {
  name: "John Doe",
  age: 23,
  otherDetails: {
    salary: 50000,
  },
};

johnDetails.otherDetails.salary = 40000; // ✅ Valid.

That's all 😃!

Feel free to share if you found this useful 😃.