TypeScriptで関数戻り値の型をユニオン型で扱うパターンを完全ガイド!初心者でもわかる型システム入門
生徒
「TypeScriptでは関数の戻り値に複数の型を使うことができますか?」
先生
「もちろんできますよ。ユニオン型を使うと、戻り値が状況によって変わる関数を作ることができます。」
生徒
「どんな場面で使うんですか?」
先生
「それでは、実際の例を見ながら学んでいきましょう!」
1. ユニオン型とは?
まずは、ユニオン型について理解しましょう。ユニオン型とは、「複数の型のうちどれかになる型」を表すものです。例えば、文字列か数値かどちらかである可能性がある値を扱うときに使います。この仕組みにより、柔軟なプログラムを書くことができます。
現実の例で言えば、お店で品物を注文するとき、「現金」か「クレジットカード」かで支払い方法が変わることがあります。TypeScriptでは、「現金 | クレジットカード」と2つの選択肢を|でつなぎます。
let pay: "cash" | "credit";
pay = "cash";
pay = "credit";
2. 関数戻り値にユニオン型を使うとは?
関数の戻り値とは、その関数を実行したときに返される値のことです。関数の結果が状況によって変わることがある場合、ユニオン型はとても便利です。
例えば、入力された数値が正しい場合は数値を返し、間違っている場合はエラーメッセージ(文字列)を返す…というような機能です。
function parseAge(age: string): number | string {
const num = Number(age);
if (isNaN(num)) {
return "数字ではありません";
}
return num;
}
number | stringと定義することで、戻り値が数値になる場合と文字列になる場合の両方に対応できます。
3. 実際の実行結果を見てみよう
console.log(parseAge("20"));
console.log(parseAge("abc"));
20
数字ではありません
上の例では、入力が正しい場合と間違っている場合で、戻り値の型が異なります。このような処理は、Webフォーム入力のチェックなどでよく使われます。
4. 戻り値がユニオン型だとどう活用できる?
ユニオン型は便利ですが、そのまま値を扱うときには少し注意が必要です。それは、プログラム側が「どちらの型が返ってきたか」を判断しないといけないからです。
そこで登場するのが型ガードです。型ガードとは、「返ってきた値がどの型かを判定する文法」のことです。
const result = parseAge("abc");
if (typeof result === "string") {
console.log("エラー:", result);
} else {
console.log("年齢:", result);
}
エラー: 数字ではありません
このように、typeofを使うことで、数値の場合と文字列の場合で処理を分けることができます。まさに、柔軟で安全なプログラミングを実現できます。
5. 関数戻り値ユニオン型を使う場面の例
次のようなシステムで役立ちます:
- 利用者の入力チェック
- ログイン認証機能での成功と失敗の結果
- 通信結果が成功かエラーかを返す処理
- API呼び出し結果を分岐させる処理
例えばログイン機能では、成功時は「ユーザー情報」、失敗時は「エラーメッセージ」を返す場合もありますよね。このようなケースにピッタリです。
6. よくある注意点
戻り値がユニオン型の場合、以下に注意しましょう。
- 型判定(型ガード)を忘れないこと
- どちらの型にも共通するプロパティしか直接は使えないこと
- 複雑になりすぎたら型設計を見直すこと
特に初心者のうちは、「今扱っている値が何の型なのか?」を確認しながら進めると安心です。
まとめ
関数戻り値をユニオン型で設計する意味
この記事では、TypeScriptにおける関数戻り値のユニオン型という考え方を中心に学んできました。関数の戻り値は、処理結果を呼び出し元へ返す重要な役割を持っています。JavaScriptでは戻り値の型が実行時まで分からないことが多く、予期しないエラーにつながることもありました。しかしTypeScriptでは、ユニオン型を使うことで「どのような型が返る可能性があるのか」を明確に表現できます。
特に、入力チェックや通信処理、認証処理などでは、成功時と失敗時で異なる値を返したい場面が頻繁にあります。数値か文字列、正常結果かエラーメッセージなど、状況によって戻り値が変わる関数は珍しくありません。そうしたケースでユニオン型を使えば、柔軟さと安全性の両方を保った実装が可能になります。
型ガードと組み合わせた安全な扱い方
戻り値をユニオン型にした場合、その値を使う側では「今どの型なのか」を意識する必要があります。そこで重要になるのが型ガードです。typeofを使った基本的な型ガードを行うことで、TypeScriptは自動的に型を絞り込み、安全に値を扱えるようになります。
型ガードを正しく使うことで、エラーを事前に防ぎ、読みやすく理解しやすいコードを書くことができます。これは初心者にとっても大きなメリットであり、プログラムの流れを自然に理解する助けにもなります。
function checkScore(score: string): number | string {
const value = Number(score);
if (isNaN(value)) {
return "数値として正しくありません";
}
return value;
}
const result = checkScore("80");
if (typeof result === "number") {
console.log("点数は", result);
} else {
console.log("エラー内容:", result);
}
このように、関数側ではユニオン型で可能性を示し、呼び出し側では型ガードで分岐するという流れを意識すると、TypeScriptらしい堅実な設計が身についていきます。
実務で役立つ考え方と設計のコツ
実際の開発現場では、関数戻り値にユニオン型を使うことで、処理結果の意図をコード上で表現できます。「成功すればこの型」「失敗すればこの型」と決めておくことで、後からコードを読む人も安心して理解できます。これは、個人開発だけでなく、チーム開発においても非常に重要なポイントです。
ただし、ユニオン型を増やしすぎると処理が複雑になる場合もあります。そのようなときは、戻り値の構造を見直したり、オブジェクト型にまとめたりするなど、設計そのものを整理することも大切です。TypeScriptの型システムは、正解が一つではなく、状況に応じた選択が求められます。
生徒
「関数の戻り値にユニオン型を使うと、処理結果のパターンが分かりやすくなるんですね。」
先生
「そうです。特に成功と失敗が分かれる処理では、ユニオン型がとても役に立ちます。」
生徒
「でも、そのまま使うときは型ガードが必要なんですよね。」
先生
「その通りです。型ガードを使えば、今どの型なのかを安全に判断できます。」
生徒
「TypeScriptは制約が多いと思っていましたけど、考え方が整理されて楽になりました。」
先生
「型は制限ではなく、正しい実装へ導いてくれる道しるべなんですよ。」