参考にさせていただいたページ
- How to Change readonly Properties to be Writable in TypeScript? - Designcise
- Change a readonly property to mutable in TypeScript | bobbyhadz
- Improved control over mapped type modifiers: TypeScript: Documentation - TypeScript 2.8
サンプルコード
ただ値を複製して使いたい場合
ただ値を複製して使いたい場合は以下のようにスプレッド構文を使えば別のオブジェクトになりreadonlyが解除されますし、新しく作ったmutableExampleObjを変更する分にはreadonlyExampleObjに影響も無いので問題ありません。以下のサンプルコードのように as MutableType<ReadonlyExampleObjType>
までするかどうかは実現したい要件次第だとは思います。この場合はそこまでしなくてもstring型であるこは推論されますし。
type ReadonlyExampleObjType = { readonly hoge: string; readonly foo: string; }; type MutableType<T> = { -readonly [Key in keyof T]: T[Key]; }; const readonlyExampleObj: ReadonlyExampleObjType = { hoge: 'hoge', foo: 'foo', } as const; const mutableExampleObj = { ...readonlyExampleObj } as MutableType<ReadonlyExampleObjType>; mutableExampleObj.hoge = 'newHoge'; // 上書きできる
どうしてもreadonlyなプロパティを書き換えたい場合
こんなことをしたくなる場合はそもそも設計がおかしいとは思いますが、まぁ事情は色々あると思いますし参考までに書いておきます。
type ReadonlyExampleObjType = { readonly hoge: string; readonly foo: string; }; type MutableType<T> = { -readonly [Key in keyof T]: T[Key]; }; const readonlyExampleObj: ReadonlyExampleObjType = { hoge: 'hoge', foo: 'foo', } as const; const mutableExampleObj = readonlyExampleObj as MutableType<ReadonlyExampleObjType>; readonlyExampleObj.hoge = 'newHoge'; // Cannot assign to 'hoge' because it is a read-only property. mutableExampleObj.hoge = 'newHoge'; // こっちは上書きできる // 当たり前ですが、readonlyHogeも書き変わるので注意!! console.log('readonlyExampleObj: ', readonlyExampleObj); // { hoge: 'newHoge', foo: 'foo' }
スプレッドした後に深いところのオブジェクトのプロパティはどうなるのか
あくまでスプレッド構文によってreadonlyが解除されるのは一階層目のプロパティだけなので、以下の場合bazはreadonlyのままです。
type ReadonlyExampleObjType = { readonly hoge: string; readonly foo: { readonly baz: 'baz' }; }; const readonlyExampleObj: ReadonlyExampleObjType = { hoge: 'hoge', foo: { baz: 'baz', }, } as const; const mutableExampleObj = { ...readonlyExampleObj }; mutableExampleObj.foo.baz = 'newBaz'; // Cannot assign to 'baz' because it is a read-only property.