ジェネリクスの型引数を明示すると戻り値の型チェックが効く
function firstOf<T>(items: T[]): Tのようなジェネリック関数は、呼び出し時に指定した型引数(例: firstOf<number>)に応じて戻り値の型が決まります。その型と違う型の変数で受け取ろうとするとエラーになります。
エラーメッセージの読み方
main.ts(4,7): error TS2322: Type 'number' is not assignable to type 'string'.
main.ts- ファイル名
4- 行番号
7- 列番号 — この位置でtscが検査に失敗しました
TS2322- エラーコード — 検索するとTypeScriptの解説が見つかります
Type 'number' is not assignable to type 'string'.- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 function firstOf<T>(items: T[]): T { 2 return items[0]; 3 } 4 const result: string = firstOf<number>([1, 2, 3]); ^ 5 console.log(result);
main.ts(4,7): error TS2322: Type 'number' is not assignable to type 'string'.
firstOf<number>を指定した時点で戻り値の型はnumberに決まります。string型の変数では受け取れません。
直し方: string を number にします。
広告
広告スロット(未設定)
パターン2
1 function lastOf<T>(items: T[]): T { 2 return items[items.length - 1]; 3 } 4 const result: boolean = lastOf<string>(["a", "b"]); ^ 5 console.log(result);
main.ts(4,7): error TS2322: Type 'string' is not assignable to type 'boolean'.
lastOf<string>によって戻り値はstring型に決まります。boolean型の変数へは代入できません。
直し方: boolean を string にします。
パターン3
1 function wrap<T>(value: T): T[] { 2 return [value]; 3 } 4 const result: string[] = wrap<number>(5); ^ 5 console.log(result);
main.ts(4,7): error TS2322: Type 'number[]' is not assignable to type 'string[]'.
wrap<number>の戻り値はnumber[]です。string[]型の変数では受け取れません。
直し方: string[] を number[] にします。
よくある誤解
「ジェネリクスは型を問わず何でも受け入れる便利な仕組み」という理解は半分だけ正しいです。関数の中身は確かに型を問いませんが、呼び出し時に決まった型引数は、戻り値を受け取る側でも厳密にチェックされます。
まとめ
ジェネリクスの型引数を明示すると戻り値の型チェックが効くは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。