MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
TypeScriptの基礎 - ユニオン型のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
TypeScriptの基礎 - ユニオン型
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == ユニオン型 (Union Type) とは、TypeScriptにおいて2つ以上の型を組み合わせ、そのいずれかの値を取り得ることを表現する型定義の仕組みである。<br> パイプ文字 <code>|</code> で複数の型を連結して定義し、変数や関数パラメータ、戻り値に対して複数の型を許容させることができる。<br> <br> ユニオン型はTypeScriptの型システムの中核を成す機能の1つであり、<code>any</code> 型に頼ることなく値の不確実性を型レベルで安全に表現できる。<br> <br> TypeScript 5.4以降では、クロージャ内でのユニオン型の絞り込み精度が向上し、TypeScript 5.5では配列の <code>filter()</code> 後の型推論も改善された。<br> <br> また、TypeScript 6.0 (2026年2月リリース) ではデフォルト設定に <code>strict: true</code> が採用され、ユニオン型を含む型チェック全般がより厳密になっている。<br> <br> * <code>|</code> 演算子によるユニオン型の宣言構文 *: 変数、関数パラメータ、戻り値への適用方法 * 文字列・数値リテラル型のユニオン *: 取り得る値を列挙型のように限定するパターン * ユニオン型に対する共通メソッドの呼び出し制約 *: ユニオンを構成する全ての型に存在するメソッドのみ使用可能 * <code>typeof</code> 等による型の絞り込み (Type Narrowing) *: 具体的な型を識別して各型固有の操作を行う手法 * 判別可能なユニオン (Discriminated Union) *: 共通の判別子プロパティ (リテラル型) により TypeScript が型を自動識別するパターン * 網羅性チェック (Exhaustive Check) *: <code>never</code> 型を活用して全てのケースを処理漏れなく対応する手法 * <code>string | null</code> 等の nullable な型 *: <code>null</code> や <code>undefined</code> を含むユニオン型と、オプショナルチェーニングの活用 * APIレスポンスやイベントハンドラ等の実用的な型定義パターン *: 実際の開発で頻出するユニオン型の応用例 <br><br> == ユニオン型の宣言 == ==== 基本的な構文 ==== ユニオン型は、<code>|</code> 演算子で複数の型を連結して宣言する。<br> <br> 変数へのユニオン型の宣言例を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> // 変数の宣言 let id: string | number; id = "user123"; // OK id = 42; // OK id = true; // エラー : booleanはユニオン型に含まれていない </syntaxhighlight> <br> 関数パラメータと戻り値への適用例を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> // 関数パラメータでの使用 function printId(id: string | number) { console.log("ID: " + id); } printId(101); // OK printId("202"); // OK // 関数の戻り値 function getUser(id: number): { name: string } | null { if (id === 1) { return { name: "Alice" }; } return null; } </syntaxhighlight> <br> 配列要素の型にユニオン型を使用する場合、<code>()</code> でユニオン型を囲む必要がある。<br> <br> <syntaxhighlight lang="typescript"> // 配列要素の型定義 let values: (string | number)[]; values = ["hello", 42, "world"]; // OK // 型エイリアスとの組み合わせ type StringOrNumber = string | number; type StringNumberOrBoolean = StringOrNumber | boolean; </syntaxhighlight> <br> ==== リテラル型のユニオン ==== 文字列・数値などのリテラル型を組み合わせることにより、取り得る値を限定したユニオン型を定義できる。<br> <br> この手法は、列挙型のような用途に活用される。<br> <br> * 文字列リテラル型のユニオン例 *: <syntaxhighlight lang="typescript"> type Status = "pending" | "success" | "error"; function handleStatus(status: Status) { switch (status) { case "pending": console.log("処理中..."); break; case "success": console.log("完了しました"); break; case "error": console.log("エラーが発生しました"); break; } } handleStatus("pending"); // OK handleStatus("complete"); // エラー : "complete"はStatus型に含まれていない </syntaxhighlight> *: <br> * 数値リテラル型のユニオン例 *: <syntaxhighlight lang="typescript"> type HttpStatus = 200 | 201 | 400 | 404 | 500; function respond(status: HttpStatus) { console.log("HTTPステータスコード: " + status); } </syntaxhighlight> <br> リテラル型の数が多い場合は、縦に並べる記述で可読性を高めることができる。<br> <br> <syntaxhighlight lang="typescript"> type Direction = | "north" | "south" | "east" | "west"; </syntaxhighlight> <br><br> == ユニオン型の操作 == ==== 共通メソッドの呼び出し ==== ユニオン型の値に対してメソッドを呼び出す場合、ユニオンを構成する全ての型に存在するメソッドのみ呼び出すことができる。<br> <br> <syntaxhighlight lang="typescript"> function process(value: string | number) { value.toString(); // OK : 全ての型に共通するメソッド value.toUpperCase(); // エラー : numberには、toUpperCase()が存在しない value.toFixed(2); // エラー : stringには、toFixed()が存在しない } </syntaxhighlight> <br> 下表に、<code>string | number</code> で使用可能なメソッド・使用不可能なメソッドの例を示す。<br> <br> <center> {| class="wikitable" |+ string | number で使用可能 / 不可能なメソッドの比較 ! 分類 !! メソッド・プロパティ !! 説明 |- | 使用可能 (共通) || <code>toString()</code> || 文字列に変換する。 |- | 使用可能 (共通) || <code>valueOf()</code> || プリミティブ値を返す。 |- | stringのみ || <code>toUpperCase()</code> || 大文字に変換する。 |- | stringのみ || <code>toLowerCase()</code> || 小文字に変換する。 |- | stringのみ || <code>charAt()</code> || 指定インデックスの文字を返す。 |- | stringのみ || <code>slice()</code> || 部分文字列を返す。 |- | stringのみ || <code>trim()</code> || 前後の空白を除去する。 |- | stringのみ || <code>length</code> || 文字列の長さを返す。 |- | numberのみ || <code>toFixed()</code> || 小数点以下の桁数を指定して文字列化する。 |- | numberのみ || <code>toPrecision()</code> || 有効桁数を指定して文字列化する。 |- | numberのみ || <code>toExponential()</code> || 指数表記の文字列に変換する。 |} </center> <br> ==== 型の絞り込みによるアクセス ==== 型固有のメソッドにアクセスするには、型の絞り込みが必要になる。<br> <br> <code>typeof</code> 演算子等を使用して具体的な型を識別することにより、各型のメソッドを安全に呼び出せる。<br> <br> <syntaxhighlight lang="typescript"> function processValue(value: string | number) { if (typeof value === "string") { // この分岐内では、valueはstring型として扱われる console.log(value.toUpperCase()); // OK } else { // この分岐内では、valueはnumber型として扱われる console.log(value.toFixed(2)); // OK } } </syntaxhighlight> <br> <u>型の絞り込みには <code>typeof</code> の他にも、<code>instanceof</code>、<code>in</code> 演算子、判別可能なユニオン等の複数の手法がある。</u><br> <br> 詳細は、[[TypeScriptの基礎 - 型の絞り込み]]のページを参照すること。<br> <br><br> == 判別可能なユニオン (Discriminated Union) == ==== 基本概念 ==== 判別可能なユニオン (Discriminated Union) とは、ユニオンを構成する各型が共通のリテラル型プロパティ (判別子) を持つパターンである。<br> TypeScript はその判別子の値によって型を自動的に絞り込むことができる。<br> <br> 判別可能なユニオンを構成するには、以下の条件を満たす必要がある。<br> <br> * ユニオンを構成する全ての型が、同名のプロパティを持つ。 * そのプロパティの型が各型ごとに異なるリテラル型である。 * そのプロパティの値によって型を一意に識別できる。 <br> ==== 実装パターン ==== 判別子として <code>kind</code> プロパティを使用した基本的なパターンを以下に示す。<br> <br> <syntaxhighlight lang="typescript"> type Result = | { kind: "success"; value: string } | { kind: "error"; error: Error } | { kind: "loading" }; function handleResult(result: Result) { if (result.kind === "success") { console.log("値:", result.value); // valueにアクセス可能 } else if (result.kind === "error") { console.log("エラー:", result.error.message); // errorにアクセス可能 } else { console.log("読み込み中..."); } } </syntaxhighlight> <br> switch文との組み合わせは、判別可能なユニオンで最もよく使われるパターンである。<br> <br> <code>type</code> プロパティを判別子として使用した図形の面積計算の例を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> interface Square { type: "square"; size: number; } interface Rectangle { type: "rectangle"; width: number; height: number; } interface Circle { type: "circle"; radius: number; } type Shape = Square | Rectangle | Circle; function calculateArea(shape: Shape): number { switch (shape.type) { case "square": return shape.size * shape.size; case "rectangle": return shape.width * shape.height; case "circle": return Math.PI * shape.radius * shape.radius; } } </syntaxhighlight> <br> 上記の例では、switch文の各caseブロック内でTypeScriptが型を正確に識別するため、<br> 各型固有のプロパティ (<u>size</u>、<u>width</u>、<u>radius</u> 等) に安全にアクセスできる。<br> <br> ==== 網羅性チェック (Exhaustive Check) ==== <code>never</code> 型を活用することにより、ユニオン型の全てのケースを処理しているかどうかをコンパイル時に検証できる。<br> この手法を、<u>網羅性チェック (Exhaustive Check)</u> と呼ぶ。<br> <br> <syntaxhighlight lang="typescript"> function assertNever(x: never): never { throw new Error("予期しない値です: " + x); } type Status = "pending" | "success" | "error"; function handleStatus(status: Status): void { switch (status) { case "pending": console.log("処理中"); break; case "success": console.log("成功"); break; case "error": console.log("エラー"); break; default: // 全てのケースを処理済みなら、statusの型はneverになる assertNever(status); } } </syntaxhighlight> <br> 上記の例において、Status型に"retry"を追加した場合、<u>case "retry":</u> が存在しないため、defaultブランチに到達する。<br> その時点で、statusの型は"retry"となり、never型を期待するassertNeverに渡せなくなるため、コンパイルエラーが発生する。<br> <br> <u>この仕組みにより、ユニオン型にメンバを追加した時の処理漏れをコンパイル時に検出できる。</u><br> <br><br> == ユニオン型の実用パターン == ==== 関数パラメータでの使用 ==== ユニオン型を関数パラメータに使用することにより、複数の型の入力を柔軟に受け付ける関数を定義できる。<br> <br> イベントハンドラの型定義の例を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> type AppEvent = | { type: "click"; x: number; y: number } | { type: "keydown"; key: string; ctrlKey: boolean } | { type: "submit"; formData: Record<string, string> }; function handleEvent(event: AppEvent) { switch (event.type) { case "click": console.log(`クリック位置: (${event.x}, ${event.y})`); break; case "keydown": console.log(`キー: ${event.key}, Ctrl: ${event.ctrlKey}`); break; case "submit": console.log("フォームデータ:", event.formData); break; } } </syntaxhighlight> <br> ==== APIレスポンスの型定義 ==== APIレスポンスの状態 (ローディング、成功、エラー) をユニオン型で表現することは、実際の開発でよく使用されるパターンである。<br> <br> <syntaxhighlight lang="typescript"> type ApiResponse<T> = | { status: "loading" } | { status: "success"; data: T } | { status: "error"; error: string; code: number }; type User = { id: number; name: string }; function renderUser(response: ApiResponse<User>) { switch (response.status) { case "loading": console.log("読み込み中..."); break; case "success": console.log(`ユーザ名: ${response.data.name}`); break; case "error": console.log(`エラー (${response.code}): ${response.error}`); break; } } </syntaxhighlight> <br> このパターンでは、ジェネリクス型パラメータ <code>T</code> を使用することにより、ユーザ、商品、投稿等の異なるデータ型に対して同じApiResponse型を再利用できる。<br> <br> ==== nullableな型 ==== <u>null</u> や <u>undefined</u> を含むユニオン型は、値が存在しない可能性を型で表現するために使用する。<br> <br> <syntaxhighlight lang="typescript"> // string | null function getUserName(id: number): string | null { if (id === 1) return "Alice"; return null; } const name = getUserName(1); // nullチェックによる型の絞り込み if (name !== null) { console.log(name.toUpperCase()); // OK : この分岐内で、nameはstring型 } // Nullish Coalescing演算子 (??) によるnullのデフォルト値設定 const displayName = name ?? "匿名"; </syntaxhighlight> <br> オプショナルパラメータ (<code>?</code>) は、自動的に <u>undefined</u> をユニオン型に追加する。<br> <br> <syntaxhighlight lang="typescript"> // valueの型は string | undefined function printValue(value?: string) { // オプショナルチェーニングにより、undefinedでも安全にアクセスできる console.log(value?.toUpperCase()); } </syntaxhighlight> <br> 型アサーションを使用して、nullableな型を非nullableとして扱う方法については、[[TypeScriptの基礎 - 型アサーション]]のページを参照すること。<br> <br><br> == 関連情報 == * [[TypeScriptの基礎 - tsconfig.json]] * [[TypeScriptの基礎 - 型注釈とプリミティブ型]] * [[TypeScriptの基礎 - 型推論]] * [[TypeScriptの基礎 - 型エイリアス]] * [[TypeScriptの基礎 - オブジェクト型とインターフェース]] * [[TypeScriptの基礎 - 関数の型定義]] * [[TypeScriptの基礎 - ユニオン型]] * [[TypeScriptの基礎 - 型の絞り込み]] * [[TypeScriptの基礎 - 型アサーション]] <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Rust]][[カテゴリ:Web]]
TypeScriptの基礎 - ユニオン型
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse