Programmingフロントエンド開発者

TypeScriptのPickはどのように機能し、このユーティリティ型は何のためにあるのか、Omitとの違いは何ですか?

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

回答。

ユーティリティ型Pick<T, K>は、既存の型やインターフェースから一部のフィールドを選択的にコピーするためにTypeScriptに追加されました。

問題の経緯

開発中に同じデータ構造がわずかに異なる形で再利用されることが多く、Pickが登場する前は、必要なフィールドを手動でコピーして新しいインターフェースを作成する必要があり、このことがコードの重複や元の構造の変更時にエラーを引き起こしていました。

問題

冗長性を避け、契約を最大限具体化するために、大きなインターフェースの一部のフィールドを使用して関数の入力または出力データを型付けする必要があります。

解決策

Pickは、キーKによって型Tのプロパティのサブセットを抽出する問題を解決します:

type Pick<T, K extends keyof T> = { [P in K]: T[P] };

例:

interface User { id: number; name: string; email: string; } type Credentials = Pick<User, 'email' | 'name'>; const creds: Credentials = { email: "user@example.com", name: "User Name", };

主な特徴:

  • 必要なキーのみを持つ新しい型を構成します;
  • selectクエリ、フォーム、出力の型付けに非常に便利です;
  • 手動コードの量とリファクタリング時のエラーを最小限に抑えます。

トリッキーな質問。

PickはOmitと何が違いますか?

Pickは型の指定されたフィールドのみを選択し、Omitは逆にそれらを構造から除外します。

type PartialUser = Omit<User, 'id'>; // idを除くすべてのフィールド

Pickを使って存在しないプロパティを選ぶことはできますか?

いいえ、キーKは必ず元の型のキーでなければならず、そうでない場合はコンパイルエラーが発生します。

Pickはオプショナルまたはreadonlyのフィールドに影響を与える可能性がありますか?

Pickは、元の型にオプショナルまたはreadonlyの修飾子が存在する場合、それらを新しい型にコピーします。

タイプエラーとアンチパターン

  • Pickの中で明示的に文字列で列挙する("id, name")ことは、キーの配列としてではなく、コンパイルエラーを引き起こします。
  • 存在しないフィールドを選択することや、キーの不適切な自動生成。
  • プロパティの除外や変更が必要な場合にPickを使用すること — そのためにOmit、Partial、Requiredがあります。

実生活の例

ネガティブケース

データ入力フォームの作成時、開発者は新しい必須属性を忘れて手動で独自の型を記述しました。インターフェースの更新後、フォームが壊れました。

利点:

  • 構造が明示的に記述されています。

欠点:

  • typedefが古くなるリスク、高いリファクタリング時のバグの可能性。

ポジティブケース

必要なフィールドを選択するためにPickが使用されます:

type FormFields = Pick<User, 'email' | 'name'>;

Userの変更が自動的にフォームに反映されます。

利点:

  • 型の保証された同期。

欠点:

  • ビジネスロジックにサポートされていない余分なフィールドを選択しないようにコントロールする必要があります。