こんにちは。TypeScriptの世界へようこそ。
TypeScriptの型システムは、単なる「エラーを防ぐための道具」ではありません。それは、「あなたのコードがどのように振る舞うべきか」という設計図を、コンパイラという最強のパートナーと共有するための言語です。
今日は、多くの開発者が何気なく使い、しかしその本質を見落としがちな「読み取り専用(Readonly)」の強制について深掘りしていきましょう。これを知るだけで、あなたの書く関数の信頼性は劇的に向上します。
—
なぜ、関数の中で「破壊」が起きてはいけないのか
プログラミングの現場で最も恐ろしいバグの一つは、「意図しない副作用」です。関数にオブジェクトを渡したつもりが、その関数の中で中身を書き換えられてしまい、呼び出し元のデータまで変わってしまう……。
function updateScore(user: { score: number }) {
// 悪気はないが、元のオブジェクトを書き換えてしまっている
user.score += 10;
}
const player = { score: 0 };
updateScore(player);
console.log(player.score); // 10 になってしまった!
これ、小さいプログラムなら良いですが、巨大なアプリケーションでは「どこでデータが変わったのか」を追跡するだけで数時間を溶かすことになります。これを防ぐのが `Readonly
—
Readonlyで「不変(Immutable)」を強制する
TypeScriptには、オブジェクトのプロパティを「読み取り専用」にする魔法があります。引数の型に `Readonly
実践:Readonlyを用いた防御的プログラミング
interface User {
name: string;
score: number;
}
// Readonly を使って「この関数は中身をいじらないよ!」と宣言する
function printUser(user: Readonly
console.log(`User: ${user.name}, Score: ${user.score}`);
// もしここで書き換えようとすると…?
// user.score = 100; // エラー: Cannot assign to ‘score’ because it is a read-only property.
}
このコードを見てください。コンパイラが「おっと、そこは書き換えてはいけない場所だぞ」と即座に教えてくれます。これがTypeScriptの強みです。実行する前に、ミスを論理的に排除する。 これがプロの仕事です。
—
よくある落とし穴:Readonlyの「深さ」に注意
初心者が陥りやすい罠が、「Readonlyは浅い」という点です。例えば、オブジェクトの中にさらにオブジェクトがある場合、外側を `Readonly` にしても内側までは保護されません。
interface State {
config: { theme: string };
}
function processState(state: Readonly
// これはエラーになる(保護されている)
// state.config = { theme: ‘dark’ };
// しかし、これはエラーにならない!
state.config.theme = ‘dark’; // 危険!副作用が発生する
}
これを防ぐには、TypeScript 3.4以降で導入された `const` アサーションや、再帰的に読み取り専用にする `DeepReadonly` 型を自作する必要があります。実務では、`Readonly
—
なぜこの設計パターンが「最強」なのか
私がこのパターンを強く推奨する理由は、「関数のインターフェースを見るだけで、その関数の安全性がわかるから」です。
1. 型を見るだけで、副作用がないと確信できる。
2. コンパイラがガードしてくれるので、安心して他のコードに集中できる。
3. 将来の自分がコードを修正する際、うっかり書き換えても怒られるので安全。
コードは「書く」ことよりも「読み返される」時間の方が圧倒的に長いものです。未来の自分やチームメンバーに対して、「このデータは壊さないから安心して使ってね」と型でメッセージを残す。これが、TypeScriptを掌握するエンジニアの姿勢です。
—
まとめ:あなたのコードを「不変」に守ろう
最後に、今回のポイントをまとめます。
- `Readonly
` は、意図しない副作用を防ぐ防波堤。 - 「書き換えない」という意思を型で表明する。
- ただし、ネストされたオブジェクトの「深さ」には注意を払う。
ここをクリアすれば、あなたの書くコードは一気にプロフェッショナルな品質に近づきます。型システムをただの「制約」と捉えるのではなく、「安全に速く走るためのガードレール」だと思って、ぜひ積極的に `Readonly` を使ってみてください。
何か分からないことがあれば、いつでも聞いてくださいね。TypeScriptの道は奥が深いですが、一歩ずつ進めば必ず景色が変わりますよ。応援しています!