やあ、TypeScriptの世界へようこそ。言語の深淵を覗き込み、コンパイラの脳内をトレースする旅へようこそ。
今日は、TypeScriptの「型システムの根幹」とも言える、関数の引数とプロパティの制御について話をしよう。多くの人がここで躓く「オプショナル引数」と「プロパティの必須化」。これらをマスターすることは、単なる文法習得ではなく、あなたの書くコードの「安全性」を設計する力を身につけることと同義です。
一緒に、現場で即戦力となる知識を紐解いていきましょう。
—
1. そもそも「オプショナル(?)」とは何者か?
TypeScriptにおいて、`?` をつけることは「その値は `undefined` である可能性がある」という神の宣告です。
function setupUser(name: string, age?: number) {
// ageは number | undefined と評価されます
console.log(`名前: ${name}`);
if (age !== undefined) {
console.log(`年齢: ${age + 1}`); // 狭められた(Type Narrowing)ので安心
}
}
ここで初心者が陥りやすい罠が、「なぜ `age` は `number` じゃないの?」という疑問です。コンパイラから見れば、`age` が渡されない場合、実行時の値は `undefined` です。型システムは実行時の「不在」を厳格に管理します。 これがTypeScriptがJavaScriptの「動的ゆえの事故」を防ぐ要なのです。
—
2. 「特定の条件で必須になる」という要件をどう解くか?
実務では、「`type` が ‘admin’ なら `role` が必須」「`method` が ‘POST’ なら `body` が必須」といった複雑な条件に直面します。
ここで初心者は `?` を乱用しがちですが、それは型安全性を放棄する行為です。真に実力のあるエンジニアは、「ディスクリミネート・ユニオン(判別可能な共用体)」という強力な武器を使います。
コードで見る「必須化」の極意
例えば、ユーザーの権限設定を考えてみましょう。
// 1. 各パターンを別々の型として定義する
type Guest = { type: ‘guest’ };
type Admin = { type: ‘admin’; role: string }; // ‘admin’の時はroleが必須!
// 2. それらをユニオン型で繋ぐ
type UserConfig = Guest | Admin;
function configure(config: UserConfig) {
if (config.type === ‘admin’) {
// ここでは config は Admin 型として確定する
console.log(`管理者権限: ${config.role}`);
} else {
console.log(“ゲストとして接続”);
}
}
// 実行してみよう
configure({ type: ‘guest’ }); // OK
configure({ type: ‘admin’, role: ‘root’ }); // OK
// configure({ type: ‘admin’ }); // Error: プロパティ ‘role’ が足りません!
ここがポイントです:
もしここで `type` を見ずに `config.role` にアクセスしようとすると、TypeScriptは「それは存在しないかもしれない」と怒ります。この「型同士の繋がり」を定義する力こそが、中級者とプロフェッショナルの分かれ道です。
—
3. なぜ「オプショナル」を安易に使ってはいけないのか?
`?` を多用すると、あなたのコードは「あらゆる場所で null チェックが必要なスパゲッティ」になります。
プロフェッショナルな設計では、以下の指針を意識してみてください。
- デフォルト値を使う: `age: number = 20` と書けば、呼び出し側は `age` を省略でき、かつ関数内では `number` 型として安全に扱えます。
- インターフェースを分ける: 「ある時とない時」で構造が大きく異なるなら、先ほどの「判別可能な共用体」を使って型を分割しましょう。
- Optionalは最後の手段: 「本当にそれがないことがシステム上正しいのか?」を自問自答してください。
—
4. 最後に:コンパイラとの対話を愛そう
TypeScriptのコンパイラは、あなたの敵ではありません。あなたのコードが実行時にクラッシュする未来を、事前に予知して教えてくれる親切なパートナーです。
「なぜここでエラーが出るんだろう?」と悩んだら、それは型システムがあなたの設計の矛盾を指摘してくれている証拠です。そのエラーメッセージを読み解き、ロジックを整理し、より強固な型を組み上げる。その繰り返しが、あなたを真のアーキテクトへと成長させます。
ここをクリアしたあなたは、もうTypeScriptの入り口を通り抜けました。次は、ジェネリクスや条件付き型(Conditional Types)といった、より深い海を一緒に探索していきましょう。
迷ったら、いつでもここに戻ってきてください。技術の根幹は、常にシンプルで美しいものですから。