TypeScriptのオプショナル型(?)を使うケースと注意点を初心者向けに解説!
生徒
「TypeScriptで、あってもなくてもいいデータを扱いたいときって、どうすればいいですか?」
先生
「そのときは、オプショナル型(?)を使うのが便利です。『?(はてなマーク)』をつけるだけで、あるかないかを自由にできますよ。」
生徒
「へぇ!それってどんな場面で使うんですか?あと、何か注意点ってありますか?」
先生
「いい質問ですね。それでは、オプショナル型の使い方と注意点を一緒に見ていきましょう!」
1. オプショナル型(?)とは?
TypeScript(タイプスクリプト)では、「あってもなくてもよい」引数やプロパティを定義したいときに、?を使います。これは「オプショナル型」と呼ばれます。
オプショナル型を使うことで、値が渡されないケースも考慮した安全なコードを書くことができます。
たとえば、次のように定義することで、「年齢は入力してもしなくてもよい」といった柔軟な設計ができます。
function greet(name: string, age?: number): void {
if (age !== undefined) {
console.log(`こんにちは、${name}さん(${age}歳)!`);
} else {
console.log(`こんにちは、${name}さん!`);
}
}
このようにageの後ろに?をつけることで、「この引数はあってもなくてもOK」という意味になります。
2. 実行結果を確認してみよう
greet("たろう", 25);
greet("じろう");
こんにちは、たろうさん(25歳)!
こんにちは、じろうさん!
1回目の呼び出しでは25という年齢を渡していますが、2回目の呼び出しではageを渡していません。それでもエラーにならず、うまく動作しているのがわかりますね。
3. オプショナル型が便利な場面
オプショナル型は、次のような場面でよく使われます:
- ユーザー登録などで「ニックネームは任意」といった場合
- 関数の引数で、一部の値だけ指定して使いたいとき
- 設定オブジェクトの一部の項目が必須でないとき
例として、オプショナルなプロパティを含むオブジェクトを定義してみましょう。
type User = {
name: string;
nickname?: string;
};
const user1: User = { name: "さくら", nickname: "さくちゃん" };
const user2: User = { name: "たけし" };
nicknameはオプショナルなので、user2のように指定しなくてもエラーになりません。
4. オプショナル型の注意点
オプショナル型を使うときには、いくつか注意しておきたいポイントがあります。
① 使う前にundefinedチェックをしよう
オプショナル型の変数は、存在しない可能性があります。なので使うときは、undefinedかどうかを確認するのが基本です。
if (user.nickname !== undefined) {
console.log(`ニックネームは${user.nickname}です`);
}
② オプショナルとデフォルト値を併用できる
関数の引数にオプショナル型と初期値を合わせて使うこともできます。たとえば次のように書くと、ageを省略した場合に18が使われます。
function introduce(name: string, age: number = 18): void {
console.log(`${name}さんは${age}歳です`);
}
③ オプショナルとnullは違う
undefinedとnullは似ていますが、意味が違います。オプショナル型は「値がない」可能性としてundefinedを想定しますが、nullは「意図的に値を空にする」ことを意味します。
必要があれば、オプショナルではなくnickname: string | nullのように、明示的にnullを許容する書き方も可能です。
5. オプショナルチェイニング(?.)との違い
似た記号に「オプショナルチェイニング(?.)」というものがありますが、これは別物です。
obj?.propのように書くことで、objがnullやundefinedであってもエラーにならず、undefinedを返してくれます。
この?.はプロパティのアクセス時に使うもので、?とは役割が異なります。
const value = user.nickname?.toUpperCase();
nicknameがなければ、valueはundefinedになります。オプショナル型と合わせて使うことで、安全なアクセスが可能です。
まとめ
TypeScriptにおけるオプショナル型(?)の使い方や注意点について、ここまでじっくりと学んできました。プログラムを書くうえで、すべての値が必ず必要とは限りません。とくに現実世界のアプリケーションでは、ユーザーが入力しなかったり、設定ファイルに一部項目がなかったりする場面がよくあります。そんなときに、「あってもなくてもOK」なオプショナル型は非常に役立ちます。
オプショナル型は、関数の引数やオブジェクトのプロパティに?を付けるだけで簡単に導入でき、柔軟な設計が可能になります。ただし、その反面で使うときにはundefinedのチェックが必要だったり、nullとは違う挙動を示すなど、注意すべき点もありました。
また、似た記号として紹介した「?.(オプショナルチェイニング)」は、オプショナル型とは用途が異なります。こちらは値の存在を確認しながらプロパティを参照するための記法であり、安全にネストされたオブジェクトを操作するのに向いています。
実際にTypeScriptでアプリケーションを開発していくと、引数が任意のときに「?」を使う、設定ファイルで「省略できる値」を表現する、チェックと合わせてエラーハンドリングするといった形で、オプショナル型の出番は多くなります。初心者のうちからこの概念に慣れておくと、より安全で読みやすいコードが書けるようになります。
オプショナル型の応用サンプル
以下は、オプショナル型とオプショナルチェイニングを組み合わせたサンプルです。
type User = {
name: string;
nickname?: string;
};
function welcome(user: User): void {
const upperNick = user.nickname?.toUpperCase();
if (upperNick) {
console.log(`${user.name}さん(ニックネーム:${upperNick})ようこそ!`);
} else {
console.log(`${user.name}さん、ようこそ!`);
}
}
welcome({ name: "みゆき", nickname: "みーちゃん" });
welcome({ name: "しんじ" });
みゆきさん(ニックネーム:ミーチャン)ようこそ!
しんじさん、ようこそ!
上記のように、オプショナル型でnicknameがないユーザーにも安全に対応しつつ、存在すれば丁寧に表示する処理が簡潔に実現できます。
このような柔軟な書き方ができるのは、TypeScriptの型システムと、オプショナルの概念のおかげです。
生徒
「オプショナル型って、ただ『?』を付けるだけで簡単に使えるんですね!」
先生
「そのとおり。ただし、値が渡されないこともあるので、ちゃんとundefinedのチェックをする癖はつけましょうね。」
生徒
「なるほど。オプショナル型と、オプショナルチェイニングの使い分けも理解できました。似てるけど別の用途なんですね!」
先生
「そうです。『定義のときに使う?』と『アクセスのときに使う?.』では使い方が違います。でも一緒に使えば、安全でエレガントなコードが書けますよ。」
生徒
「TypeScriptって、型のルールがあるから難しそうって思ってたけど、こうして覚えていくと楽しくなってきますね!」
先生
「うんうん、そうやって楽しみながら学ぶのが一番。今後も色々な型や構文を扱うことになるので、焦らず一歩ずつ進めていきましょう。」