Last updated: Feb 28, 2024
Reading timeยท2 min
You can use mapping modifiers to change a readonly property to mutable in TypeScript.
You can remove the readonly
modifier by prefixing the readonly
keyword
with a minus -
.
Here is an example when working with classes.
// โ With Classes class Employee { constructor(public readonly name: string) { this.name = name; } } // ๐๏ธ create utility type type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; const emp: Mutable<Employee> = new Employee('Bobby Hadz'); emp.name = 'Alice'; console.log(emp.name); // ๐๏ธ 'Alice'
And here is an example when working with objects.
// โ With Objects interface Person { readonly country: string; } // ๐๏ธ create utility type type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; const obj: Mutable<Person> = { country: 'Germany', }; obj.country = 'Austria'; console.log(obj); // ๐๏ธ {country: 'Austria'}
We created a Mutable
utility type that uses
mapping modifiers
to make properties in a class or object mutable.
Mapping modifiers are removed or added by prefixing them with a plus +
or
minus -
. If you don't explicitly add a prefix, then +
is assumed.
The type basically removes readonly
attributes from a type's properties.
type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; type Address = { readonly country: string; readonly city: string; }; // ๐๏ธ type MutableAddress = { // country: string; // city: string; // } type MutableAddress = Mutable<Address>;
You can also use a type assertion to cast the type of the object to mutable.
// โ With Classes class Employee { constructor(public readonly name: string) { this.name = name; } } type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; // ๐๏ธ using a type assertion const emp = new Employee('Bobby Hadz') as Mutable<Employee>; emp.name = 'Alice'; console.log(emp.name); // ๐๏ธ 'Alice'
And here is an example when working with objects.
interface Person { readonly country: string; } type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; // ๐๏ธ using type assertion const obj = { country: 'Germany', } as Mutable<Person>; obj.country = 'Austria'; console.log(obj); // ๐๏ธ {country: 'Austria'}
You might also have to do as unknown as Mutable<MyType>
if your types diverge.
any
typeIf you don't like any of the approaches, you can also cast the object to any
before changing its property. This would suppress all type-checking errors.
class Employee { constructor(public readonly name: string) { this.name = name; this.country = country; } } const emp1 = new Employee('Bobby Hadz'); // โ๏ธ Error: Cannot assign to 'name' because it is a read-only property.ts(2540) emp1.name = 'Alice'; // โ Works without errors (emp1 as any).name = 'Alice'; console.log(emp1.name); // ๐๏ธ "Alice"
I prefer to use the any type sparingly because it effectively turns off type checking.
However, when you need a quick and dirty solution, it gets the job done.