TypeScriptのunion型とは

TypeScriptのunion型(ユニオン型)とは、「AかBのどちらか」というように、複数の型のいずれかを表す型です。縦棒|で型をつなげて書きます。


なぜunion型が必要なのか
1つの値が「複数の型のどれか」になる場面は、実務でよくあります。例えば、入力欄に入れるIDが「数値のときも文字列のときもある」といったケースです。
// numberでもstringでも受け取りたい
function printId(id: number | string) {
console.log(`IDは${id}です`);
}
printId(123); // OK
printId("abc123"); // OKnumber | stringと書くことで、「numberかstringのどちらか」を受け取れる関数になります。union型がないと、型ごとに関数を分けて書く必要が出てしまいます。
リテラル型とは
union型と一緒によく使われるのが「リテラル型」です。リテラル型とは、stringやnumberのような広い型ではなく、「特定の値そのもの」を型にしたものです。
let status: "success"; // "success"という文字列しか入れられない型
status = "success"; // OK
status = "error"; // Error: Type '"error"' is not assignable to type '"success"'.単体だとあまり使い道がなさそうですが、union型と組み合わせると一気に実用的になります。
union型×リテラル型が実務で最強な理由
リテラル型をunion型でつなぐと、「決められた選択肢のどれか」を表現できます。
type Status = "loading" | "success" | "error";
function showMessage(status: Status) {
// statusには この3つ以外は渡せない
}
showMessage("success"); // OK
showMessage("finish"); // Error: 決められた値以外は渡せないAPI通信の状態(読み込み中・成功・失敗)や、ボタンの種類(primary・secondaryなど)のように、「あらかじめ決まった値のどれか」を扱う場面で大活躍します。文字列を直接比較するより、タイプミスをコンパイル時に防げるのが大きなメリットです。この書き方はtypeでしか書けないので、interfaceとの使い分けも押さえておくとよいです。
union型の値を安全に使う(型の絞り込み)
union型の値をそのまま使おうとすると、エラーになることがあります。
function printId(id: number | string) {
console.log(id.toUpperCase());
// Error: Property 'toUpperCase' does not exist on type 'number'.
}toUpperCaseは文字列のメソッドなので、numberの可能性があるidには使えません。こういうときは、typeofで型を確認してから使います(型の絞り込み)。
function printId(id: number | string) {
if (typeof id === "string") {
console.log(id.toUpperCase()); // ここではstringとして扱える
} else {
console.log(id); // ここではnumber
}
}この「使う前に型を確認する」考え方は、any・unknownの記事でも解説しています。union型でも同じ型ガードの考え方が使えます。
Reactでの使用例
ReactでAPI通信の状態を管理するとき、union型のリテラル型が定番の書き方になります。
type Status = "loading" | "success" | "error";
const [status, setStatus] = useState("loading");
// statusには決められた3つの値しか入らないので、
// タイプミスや想定外の値を防げるAPI通信の型については、こちらの記事も参考になります。
union型とenumの違い
「決められた値のどれか」を表す方法として、enumという書き方もあります。ざっくり言うと、union型のリテラル型の方がシンプルで、近年のReact開発ではこちらが好まれる傾向があります。
| 項目 | union型(リテラル型) | enum |
|---|---|---|
| 書き方 | シンプル(1行で書ける) | やや冗長 |
| コンパイル後 | 余分なコードが残らない | 実体のあるコードが生成される |
enum自体については、別の記事で改めて詳しく解説する予定です。まずはunion型のリテラル型を使いこなせるようにしておけば十分です。
よくあるエラー
type Status = "success" | "error";
const s: Status = "Success";
// Type '"Success"' is not assignable to type 'Status'.これは、大文字・小文字の違いで、決められたリテラル型に一致していないために起きるエラーです。union型のリテラル型は「値そのもの」を型にしているため、"success"と"Success"は別物として扱われます。定義した値と完全に一致しているか確認してみてください。
よくある質問
Q. union型はいくつまで型をつなげられますか?
A. 個数に実用上の制限はありません。"a" | "b" | "c" | "d"のように必要なだけつなげられます。
Q. リテラル型とunion型は違うものですか?
A. 別の概念です。リテラル型は「特定の値そのものの型」、union型は「複数の型のどれか」を表す型で、この2つを組み合わせて使うことが多いです。
Q. union型とenum、どちらを使えばいいですか?
A. 近年のReact開発では、シンプルに書けるunion型のリテラル型が好まれる傾向があります。まずはこちらに慣れておけば困りません。
まとめ
- union型は
|で複数の型をつなぎ、「AかBのどちらか」を表す型 - リテラル型(特定の値の型)と組み合わせると、「決まった選択肢のどれか」を表現できる
- union型の値を使うときは、typeofなどで型を絞り込んでから使う
- ReactのAPI状態管理などで頻繁に使う、実務必須の書き方
公式ドキュメントにも、union型についての詳しい解説があります。
▶ TypeScript公式ドキュメント:Union Types






