Borislav Hadzhiev
Tue Mar 15 2022·3 min read
Photo by Paola Chaaya
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.
// 👇️ 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.
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.
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.
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';
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.
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.
_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.