Programmingフロントエンド開発者

TypeScriptにおけるunion types(ユニオン型)の型付けメカニズムはどのようになっていますか?それは何のために必要で、型の絞り込みはどのように機能し、union typesの取り扱いにはどんなニュアンスがありますか?

Hintsage AIアシスタントで面接を突破

回答。

問題の歴史:

Union typesは、TypeScriptが異なる型の値を受け取ることができる変数やパラメータを記述するために導入されました。この機能は、従来のプログラミング言語に比べて型付けの柔軟性を大幅に向上させました。

問題:

JavaScriptでは、関数や変数は多様な型(例えば、数値や文字列など)を受け付けることが多く、安全な型付けが難しくなります。union typesがない場合、anyを使用したり、コードを重複して書く必要がありました。これは本番環境でのエラーを増やし、大規模なチームでの作業を困難にしました。

解決策:

Union typesは、異なる型のいずれかである変数を宣言できるようにし、検証後に正しい操作を保証します。また、型の絞り込み(type narrowing)をサポートしており、コンパイラが何を扱っているかを「理解」するのを助けます。

コードの例:

function formatId(id: number | string): string { if (typeof id === 'string') { return id.toUpperCase(); } return id.toString(); }

主な特徴:

  • 変数やパラメータの可能な型を明示的に指定できます。
  • 型の絞り込みメカニズムとともに機能します(例えば、typeofやinを使用した検証など)。
  • 同じキーが異なる型を持つ可能性のあるオブジェクトとの作業が複雑になります — アクセスロジックの慎重な管理が必要です。

ひっかけ質問。

プロパティが異なるオブジェクトのunionを書き、チェックなしで任意のプロパティにアクセスすることはできますか?

いいえ。Union typesは、すべての型に存在するプロパティとメソッドのみを操作できます。特定のプロパティにアクセスするには、型の絞り込みが必要です。

コードの例:

type Fish = { swim: () => void; }; type Bird = { fly: () => void; }; function move(animal: Fish | Bird) { // animal.swim(); // 絞り込みなしでエラー if ('swim' in animal) { animal.swim(); // OK } }

文字列 | 数値のunionタイプでなぜすべてのメソッドが利用できないのですか?

TypeScriptでは、unionには含まれる型すべてに存在するものだけが許可されます。個別のメソッドを使用する場合、最初に実際の型を確認する必要があります。

union内で型を確認せずに特定のメソッドを呼び出そうとするとどうなりますか?

その場合、メソッドの存在が保証されていないため、コンパイルエラーが発生します。特定の型を確認した後のみ機能します。

型のエラーとアンチパターン

  • 使用する前に型のチェックをスキップする(アクセスエラーを引き起こす可能性があります)。
  • あまりにも広範なunion typesの記述(型安全性が失われる)。
  • 不正確な絞り込みが見えないエラーやnot exhaustive checksを引き起こします。

実生活の例

ネガティブケース

変数にタイプ string | number を与え、チェックなしで toUpperCase() を実行しました。その結果、アプリケーションが数値データでクラッシュしました。

長所:

  • 急いで書かれたコード。

短所:

  • ランタイムエラー。
  • TypeScriptの静的型付けへの信頼が失われる。

ポジティブケース

メソッドを使用する前にタイプを確認します:

if (typeof value === 'string') { return value.toUpperCase(); } else { return value.toString(); }

長所:

  • コンパイル時の完全な安全性。
  • コードの保守性が向上。

短所:

  • 不要なチェックを書く必要があります。