Change a readonly property to mutable in TypeScript

avatar

Borislav Hadzhiev

Thu Mar 17 20222 min read

banner

Photo by Phuoc Le

Change a readonly property to mutable in TypeScript #

You can use mapping modifiers to change a readonly property to mutable in TypeScript, e.g. -readonly [Key in keyof Type]: Type[Key]. You can remove the readonly modifier by prefixing the readonly keyword with a minus -.

index.ts
// 👇️ 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('James'); emp.name = 'Alice'; console.log(emp.name); // 👉️ 'Alice' // -------------------------------------------- // 👇️ With Objects 👇️ interface Person { readonly country: string; } 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.

index.ts
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.

index.ts
// 👇️ With Classes 👇️ class Employee { constructor(public readonly name: string) { this.name = name; } } type Mutable<Type> = { -readonly [Key in keyof Type]: Type[Key]; }; // 👇️ using type assertion const emp = new Employee('James') as Mutable<Employee>; emp.name = 'Alice'; console.log(emp.name); // 👉️ 'Alice' // -------------------------------------------- // 👇️ With Objects 👇️ interface Person { readonly country: string; } // 👇️ 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.

If you don't like any of the approaches, you can also cast the object as any before changing its property, which would suppress type checking errors.

index.ts
class Employee { constructor(public readonly name: string) { this.name = name; this.country = country; } } const emp1 = new Employee('James'); // ⛔️ 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 type any type sparingly, because it effectively turns off type checking, but when you need a quick and dirty solution, it gets the job done.

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