イミュータブルとは、作った後に値を変更しないことです。
JavaScriptやTypeScriptでは、配列やオブジェクトを扱うときに特に重要です。
一言でいうと
イミュータブルは、元の値を書き換えず、新しい値を作って扱う考え方です。
値がどこで変わったか分からない状態を減らし、バグを追いやすくします。
ミュータブルな例
const user = { name: "Taro", point: 10 };
function addPoint(user: User) {
user.point += 1;
return user;
}
この関数は、受け取った user 自体を書き換えます。呼び出し元の値も変わるため、どこで変更されたか追いにくくなります。
イミュータブルな例
function addPoint(user: User) {
return {
...user,
point: user.point + 1,
};
}
元の user は変更せず、新しいオブジェクトを返します。
イミュータブルのメリット
| メリット | 説明 |
|---|---|
| 変更箇所を追いやすい | 値が勝手に変わりにくい |
| テストしやすい | 入力と出力を比較しやすい |
| 状態管理と相性がよい | Reactなどで変更検知しやすい |
| 並行処理に強い | 同じ値を共有しても壊れにくい |
特にフロントエンドでは、状態を直接書き換えないことが重要です。
配列の例
const users = ["Taro", "Hanako"];
const nextUsers = [...users, "Sora"];
push で元配列を変更するのではなく、新しい配列を作っています。
何でもコピーすればよいわけではない
イミュータブルを意識しすぎると、深いコピーを大量に作ってパフォーマンスや可読性が悪くなることがあります。
重要なのは、変更されると困る状態を直接書き換えないことです。ローカルな一時変数や、閉じた範囲の処理では、単純な書き換えが読みやすい場合もあります。
初学者の目安
- 関数の引数を直接書き換えない
- Reactのstateを直接変更しない
- 配列追加は
pushより新しい配列を作る - オブジェクト変更はスプレッド構文を使う
- 書き換えが必要な場合は範囲を小さくする
まずは、引数と共有状態を勝手に変えないことから始めます。
まとめ
イミュータブルは、元の値を直接変更せず、新しい値を作って扱う考え方です。
値の変更箇所を分かりやすくすることで、状態管理やデバッグが楽になります。