Cannot assign to 'X' because it is a read-only property (TS)

avatar

Borislav Hadzhiev

Tue Mar 15 20223 min read

banner

Photo by Paola Chaaya

Cannot assign to 'X' because it is a read-only property (TS) #

The error "Cannot assign to 'X' because it is a read-only property" occurs when we try to change the value of a read-only property in a class or an object. To solve the error, remove the readonly modifier or use a type assertion to change the value of the property.

Here are two examples of how the error occurs.

index.ts
// 👇️ with classes class Employee { readonly country: string = 'Germany'; changeCountry() { // ⛔️ Error: Cannot assign to 'country' because // it is a read-only property.ts(2540) this.country = 'Chile'; } } // 👇️ with objects type Person = { readonly name: string; }; const obj: Person = { name: 'James', }; // ⛔️ Error: Cannot assign to 'name' because // it is a read-only property.ts(2540) obj.name = 'Frank';

The examples above use the readonly modifier to set the class and object properties to read-only and make them immutable.

To solve the error, remove the readonly modifier if you have access to the code where it's set.

index.ts
class Employee { country = 'Germany'; changeCountry() { this.country = 'Chile'; } } type Person = { name: string; }; const obj: Person = { name: 'James', }; obj.name = 'Frank';

If you can't remove the readonly modifier, but need to change the value of the readonly property, you can use a type assertion.

index.ts
class Employee { readonly country: string = 'Germany'; changeCountry() { (this.country as any) = 'Chile'; } } type Person = { readonly name: string; }; const obj: Person = { name: 'James', }; (obj.name as any) = 'Frank';

We used type assertions to cast the read-only properties to any, so we can still change their value.

You can also be more specific and cast the readonly property to the type of the value in the assignment, which is a bit better.

index.ts
class Employee { readonly country: string = 'Germany'; changeCountry() { (this.country as string) = 'Chile'; } } type Person = { readonly name: string; }; const obj: Person = { name: 'James', }; (obj.name as string) = 'Frank';
Note that in some cases the "Cannot assign to 'X' because it is a read-only property" error occurs when you work with a third-party library and try to mutate an immutable state object.

If that's the situation you're in, there is most likely a method that the library exports that is used to mutate its state and it shouldn't be done directly by changing the state object.

If you need a way where a class property cannot that be changed from the outside, and can only be changed from within the class, you can set the property as protected and use a getter.

index.ts
class Employee { protected _country = 'Germany'; get country(): string { return this._country; } changeCountry() { this._country = 'Chile'; } } const employee = new Employee(); console.log(employee.country); // 👉️ "Germany" // ⛔️ Cannot assign to 'country' because // it is a read-only property.ts(2540) employee.country = 'Belgium';

Protected class properties can only be access from within the class and subclasses of the class.

That's why we added a getter, which allows access from outside the class.

Users cannot directly change the _country property from the outside, but they could call the changeCountry method and set it to a specific property.

You could also mark the changeCountry method as protected or change the _country property from the classes' constructor method. How you implement this depends on your use case.

Use the search field on my Home Page to filter through my more than 1,000 articles.