Code Fix

上級

ジェネリクスのextends制約を満たさない型を渡すとエラーになる

<T extends { length: number }>のように書くと、Tには「lengthプロパティを持つ型」しか渡せなくなります。制約を満たさない型(例えばnumber)を渡すと、呼び出し時点でエラーになります。

エラーメッセージの読み方

main.ts(4,23): error TS2345: Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
main.ts
ファイル名
4
行番号
23
列番号 — この位置でtscが検査に失敗しました
TS2345
エラーコード — 検索するとTypeScriptの解説が見つかります
Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  function getLength<T extends { length: number }>(item: T): number {
 2    return item.length;
 3  }
 4  console.log(getLength(42     ));
                             ^
main.ts(4,23): error TS2345: Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.

getLengthはlengthプロパティを持つ型しか受け付けません。numberにはlengthが無いため制約違反になります。

直し方: 42"hello" にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  function printId<T extends { id: number }>(item: T): void {
 2    console.log(item.id);
 3  }
 4  printId("abc"    );
                ^
main.ts(4,9): error TS2345: Argument of type 'string' is not assignable to parameter of type '{ id: number; }'.

printIdはidプロパティを持つオブジェクトしか受け付けません。文字列にはidがないため制約を満たしません。

直し方: "abc"{ id: 1 } にします。

この問題を解いてみる →

パターン3

 1  function double<T extends { value: number }>(item: T): number {
 2    return item.value * 2;
 3  }
 4  console.log(double(true        ));
                             ^
main.ts(4,20): error TS2345: Argument of type 'boolean' is not assignable to parameter of type '{ value: number; }'.

doubleはvalueプロパティを持つ型が必要です。booleanにはvalueが無いため制約に違反します。

直し方: true{ value: 5 } にします。

この問題を解いてみる →

よくある誤解

「ジェネリクスはどんな型でも受け入れる」という理解は、extends制約を付けていない場合に限った話です。制約を付けた時点で、その形を持たない型は受け付けなくなります。

まとめ

ジェネリクスのextends制約を満たさない型を渡すとエラーになるは上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)