Programmingバックエンド開発者

TypeScriptにおけるGenericsの型付けとは何か、どのようにして汎用関数やクラスを書くために使用されるのか? どんな落とし穴に出くわす可能性があるか?

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

回答。

Generics(ジェネリクス)は、異なる型で動作しながら厳密な型の安全性を維持する汎用的なコードを書くことを可能にします。

使用法の構文:

function identity<T>(value: T): T { return value; } const x = identity<string>('test'); // T = string

使用される場所:

  • コレクションの汎用関数(map、filterなど)
  • クラス(例えば、Repository<Entity>
  • インターフェース(例えば、汎用型のAPIレスポンス)

型制限のある例:

function getFirst<T extends { length: number }>(arr: T): T { return arr[0]; }

一見ひっかけ問題。

質問:ジェネリックパラメータを持つ関数を呼び出す際に具体的な型を指定する必要があるか?

回答:

必要ありません。TypeScriptは、可能な場合は渡された値に基づいて型を自動的に推論します。ただし、値から型が明確でない場合や複数の選択肢がある場合は、明示的に指定することが便利です。

function identity<T>(value: T): T { return value; } identity(5); // T = number(自動) identity<string>('s'); // T = string(明示的)

このトピックの細かい点を知らないために実際に起こったエラーの例。


物語

eコマースプロジェクトで異なるエンティティのためのジェネリックリポジトリを作成しましたが、型制限を忘れてしまいました。その結果、ジェネリックには任意のオブジェクトが含まれ、互換性のないフィールドを持つエンティティが一度保存されました。型はエラーから保護されませんでした。


物語

テンプレート関数に配列を渡しましたが、要素の型を持つ配列を受け取ると期待していました。しかし、関数はany[]を返しました。なぜなら、ジェネリックが明示的に指定されておらず、TypeScriptが型を推論できなかったからです。エラーは本番環境でのみ気づかれました。


物語

初心者の開発者が型制限なしのジェネリッククラスを作成し、すべての型に存在しないフィールドを使用しました。コンパイラはエラーを出さなかったが、存在しないプロパティにアクセスした際に全機能が壊れてしまいました。