はじめに
TypeScript、難しくないですか(少なくとも私は得意ではありません)? 特に抽象度が高くなるとすぐに脳内メモリが足りなくなるので、ずっと食わず嫌いをしていたのですが...。そうこうも言ってられなくなったので(遅い)、今更ながら勉強してみることにしました。
使用テキスト
使用したのはこちらのテキスト。コードもこちらの書籍から引用しています。全てのコードには該当ページ数も書いておきます。
ジェネリクス
まずは基本的なこちら。 「型引数に何を入れるかは関数を呼び出す際に決まる」 関数を作る機能のことだそうですが、それだけでは何のことかわかりづらいですよね。。。
つまりこういうことだそうです。
下記の場合、T
がジェネリクスで、 ①一つの呼び出し内でTには同じ値が入りますが、②Tにはどんな型でも入れることができます。
const repeat = <T>(element: T, length: number): T[] => { // ここのTにはどんな型でも入る
const result: T[] = []; // Tは関数の中で使ってもOK
for(let i = 0; i < length; i++) {
result.push(element);
}
return result;
}
プロを目指す人のためのTypeScript入門:p.170
型引数は
- 引数の型
- 返り値の型
- 関数の中
で使うことができます。(使える範囲が広すぎて鬼門だった)
こんなふうに呼び出しの際に型注釈をつけると、上記repeat
関数内のT
が全て型注釈でつけた型に置き換わります。
repeat<string>('hoge', 10) // T はstring型になる
repeat<number>(1, 10) // T はnumber型になる
repeat(0, 10) // repeatに型引数をつけなくてもOK(number型と推測される)
...が、型注釈をつけなくてもTypeScriptが推論してつけてくれます。(ここも鬼門だった)
なんなら返り値の型が無くたって推論してくれます。(さらに鬼門だった)
どおりで、ある程度適当に書いていてもうまい具合にジェネリクスが当てはまってくれるワケですね。(そして適当に書いているが故にエラーが出た時にわかりづらくなる。。。。)
参考にしたテキストによると、この機能のおかげでTypeScriptは "「好きな値で呼び出せばいい感じの返り値を返してくれる関数」として機能する" (p.172)らしいです。「混乱する!」と思ってしまった自分はTSへの愛が足りなかったようです。頑張ります。
ジェネリクスの応用
ジェネリクスって、本当に色々な使い方ができるんですよね。こちらも初学の時に一気に詰め込んだ故にわかりづらくなっていたので整理します。
複数の型引数
もちろん、型引数の複数使用も可能です。下記の例ではL
とR
にそれぞれ好きな型を割り振れます。
const pair = <L, R>(left: L, right: R): [L, R] => [left, right]
const p = pair<string, number>("tanutanu", 10)
// この時、L...string, R...number 型となる
プロを目指す人のためのTypeScript入門:p.171 のコードを一部改変
extends
extends
などを使って、型に一部だけ制約を付けることも可能です。下記は、{name: string}
というプロパティを含むオブジェクトであればコンパイルが通ります。
const repeat = <T extends { name: string }>(element: T, length: number): T[] => {
const result: T[] = [];
for(let i = 0; i < length; i++) {
result.push(element);
}
return result;
}
type PersonalInfo = {
name: string;
age: number;
hobby: string[];
}
console.log(repeat<PersonalInfo>({
name: "tanutanu",
age: 10,
hobby: ['eat', 'sleep']
}, 3))
プロを目指す人のためのTypeScript入門:p.171 のコードを一部改変
だいぶ複雑になってきましたが、丁寧に見れば読み解けそうですね
次回予告
ユニオン型、インターセクション型とジェネリクスを使って、さらに複雑な型を読み解けるようになろうかな。
▼この記事の続きはこちら
https://qiita.com/sazumy/private/83987f0abe773565b5c1