TypeScript: extends [アウトプット全くしてこなかったのでアウトプットする005]


自分のTypeScript力に全く自信を感じないため、type challengesをやって現在の自分の立ち位置を確かめようとしましたが、早速easy問題の1問目から挫折したのでアウトプットします。

ちなみに問題は以下です

問題の意味から既にわからずすぐ答えを見たのですが
答えもよくわからず、その理由として自分が今まで目を背けてきたextendsinを使用していましたのでこの際ちゃんと勉強しようと思いました。
この記事ではまずextendsについてまとめます。

extendsとは

Genericsで渡される型に対して制約をつけるものだそうです。

例えば以下の関数はジェネリクスに何も制約がついていないのでどんな方でも指定することができます。
今回はboolean型を入れています。

const returnValue = <T>(value: T): T => value;
returnValue<boolean>(true);

ただこのジェネリクスに対して制約をつけることができます。それがextendsです。

以下はextendsを使用してジェネリクスに渡す型をnumber型とstring型に限定しています。

const returnValue = <T extends number | string>(value: T): T => value;

ここで

const returnValue = <T extends number | string>(value: T): T => value;
returnValue<boolean>(true);

ジェネリクスにboolean型を渡すと
型を検知して怒ってくれます。

もうちょっと踏み込んでみる

ジェネリクスに制約なしで関数内で引数のプロパティ名を使用しようとするとジェネリクスにプロパティnameがあることが担保されていないため怒られます。

ここで以下のようにnameプロパティがある型を作成し、extendsでジェネリクスに渡される型にはnameプロパティがあることを担保してあげるとエラーが消えます。

type Student = { name: string }
const getStudentName = <T extends Student>(student: T): string => student.name

また以下のように渡す型の名前がtypoしていたりするとエラーを出してくれます。

const me = { name: 'cawauchi' }
type ErrorStudentType = { nam: string }
getStudentName<ErrorStudentType>(me)

以下は通ります。

const me = { name: 'cawauchi' }
type AdequateStudentType = { name: string, height?: 176 }
getStudentName<AdequateStudentType>(me)

extendsすごいですね。型エラー出してくれるので業務でも使える部分あったらどんどん使っていきたいです。

参照

強くなりたい!!!!!!!!!!