TypeScriptの世界へようこそ!チーフアーキテクトの私です。
フロントエンドの現場に立っていると、「うわ、誰だこのデータ書き換えたの…!?」というバグに頭を抱える夜が、エンジニアなら誰しも一度や二度(いや、もっと?)あるものです。アプリが複雑になってくると、あっちこっちのコンポーネントが勝手にデータを書き換えてしまい、状態がカオスになる。
そんな「不意打ちのデータ書き換え」という現場の悲劇を防ぐための強力な相棒が、今回紹介する `Readonly
難しい言葉は抜きにして、さっそく一緒に紐解いていきましょう。大丈夫、一歩ずつ見ていけば絶対に怖くありませんよ!
—
1. イミュータブル(変更不可)ってなぁに?
TypeScriptでコードを書いていると、「イミュータブル」というちょっとカッコいい言葉を耳にすると思います。
難しく考える必要はありません。要するに「一度作ったら、二度と中身を変えられない(書き換え禁止)」という意味です。
身近な例えで考えてみましょう。
あなたがコンビニで買った「アイスクリームのパッケージ」を想像してください。蓋を開けてスプーンを入れたら中身を食べられますよね。でも、一度食べたアイスのカップに、別のプリンを「やっぱりこっちの方がいいや」と戻したりはできませんよね(物理的にはできるかもしれませんが、そういう問題ではなく…!笑)。
あるいは、役所で発行してもらう「住民票」を思い浮かべてみてください。そこに書いてある自分の住所や名前を、ペンで「やっぱりここ引っ越したから書き換えとこっと」と勝手に修正したら……犯罪になっちゃいますよね(笑)。
プログラムの世界でもこれと同じです。
「この大事な設定データは、絶対に途中で誰にも書き換えられたくない!」
「APIから取得したユーザー情報は、表示専用だから勝手にいじってほしくない!」
そんなときに使うのが、今回主役の `Readonly
—
2. 通常のオブジェクトと `Readonly` の違い
まずは、普段よく書く普通のオブジェクトの姿を見てみましょう。
// 普通のユーザー情報の型
interface User {
name: string;
age: number;
}
// ユーザーデータを作ってみるよ
const myUser: User = {
name: “たろう”,
age: 25,
};
// 普通のオブジェクトなら、後から書き換えるのはお手のもの!
myUser.name = “次郎”; // 怒られません。スイスイ書き換わります。
myUser.age = 30; // こっちも問題なし!
普通のオブジェクトは、このようにいつでも自由にデータを塗り替えることができます。これはこれで便利なんですが、アプリが大きくなってくると「あれ? 今 `name` って誰が書き換えたんだっけ?」というデバッグの迷宮に入り込む原因になります。
そこで、登場するのが `Readonly
使い方はとってもシンプル。型を囲うように `Readonly<...>` と包んであげるだけ。
// Readonlyで包んで、絶対に書き換えられない「お触り厳禁」の型にするよ
const safeUser: Readonly
name: “花子”,
age: 22,
};
// さあ、ここでデータを書き換えようとすると……?
// safeUser.name = “三郎”;
// ❌ ここでTypeScript先生が真っ赤な波線を出して怒ってくれます!
// 「おいおい、そいつは読み取り専用(readonly)だぞ!」と。
このように、`Readonly
—
3. 実務で出会う「うっかりミス」を防ぐ具体例
Web制作やアプリ開発の現場では、例えば「設定データ」や「初期データ」を扱うときによくこの `Readonly` が使われます。
実際の現場を少し覗いてみましょう。
// アプリ全体の基本設定を表す型
interface AppConfig {
readonly apiUrl: string; // ここに直接 readonly をつけることもできます
readonly timeout: number;
}
// または、すでにある型をまとめて Readonly
interface Product {
id: number;
title: string;
price: number;
}
// カートに入れた商品の初期データ
const initialProduct: Readonly
id: 101,
title: “極上のTypeScript解説本”,
price: 3200,
};
// 【よくあるうっかりミス】
// 割引セールだからといって、うっかり価格を書き換えようとしてしまう…
// initialProduct.price = 2800; // ❌ エラー! TypeScriptがバグを未然に防いでくれた!
「えっ、じゃあセールで価格を変えたいときはどうするの?」って思いますよね。
大丈夫です。イミュータブルな世界の鉄則は、「元のデータをいじるな、新しいデータを作れ」です。
// セール品の新しいデータを作りたいときは、スプレッド構文(…)を使って新しくコピー&上書きしよう!
const saleProduct: Product = {
…initialProduct, // 既存のプロパティをパパッとコピーして
price: 2800, // 価格だけ新しくする!
};
console.log(saleProduct);
// { id: 101, title: “極上のTypeScript解説本”, price: 2800 } が完成!
このように、「元データを汚さない(イミュータブルを保つ)」ことで、アプリの動きが圧倒的に予測しやすくなり、バグの温床を綺麗に排除できるようになるんです。
—
4. チーフアーキテクトからの温かいメッセージ
初学者のうちは、「わざわざエラーが出るように制限をかけるなんて、窮屈だな〜」と感じるかもしれません。コードを書く手が止まったり、赤波線にイライラしたりすることもあるでしょう。
でも、安心してください。
TypeScriptがエラーを出してくれるのは、あなたを嫌がらせているわけではありません。「未来のあなたや、一緒に働く仲間がバグで夜中に泣かないように、今のうちに優しく教えてくれている」んです。
データ構造をカチッと固めて、どこをどう変更しても安全な状態を保つこと。これが大規模開発を生き抜くための、現代のフロントエンドエンジニアの大きな武器になります。
まずは怖がらずに、あなたのコードの「絶対に書き換えられたくない大切なデータ」を、ひとつだけ `Readonly
それでは、また次の現場でお会いしましょう!Happy Hacking!

コメント