Web開発ログ | エンジニアに役立つ情報 | 開発の中での気づきを発信

高卒Devlog

TSLab【第4回 TypeScript勉強会】ついに現れたGenerics!!

thumbnail

こんにちは! RYOTAです!

当記事をご覧くださりありがとうございます!

当記事はTSLab勉強会(定例会)のレポート記事になります!

はじめに

私が運営しているTSLabの第4回定例会の実施ログとなります。
今回のテーマは関数の型定義!
引数の型定義やジェネリクスなどの使い方を中心に学習を進めていきました!

ディスカッション内容

ジェネリクス

ジェネリクスって何なん?について各グループ議論されてましたね。
「これって必要?」「使わなくても実装は出来るよね」との意見も出てきましたが、
結論、めっちゃ使います。
バックエンドだと非同期関数のリターン型やReactだとuseStateの型定義とかですね。

// 非同期で真偽値を返す
const testAsyncFunc = async (): Promise<boolean> => {
  // ~~~~~
}

上記は既存のメソッドに型を割り当ててるだけですが、自分で汎用的な型を作るときにも押さえておきたいノウハウになります。
例えば下記のように配列の一つ目を返す関数があったとします。

/**
 * 文字列の配列を受け取って一つ目の文字列を返す
 */
const firstString = (arr: string[]): string => {
  return arr[0]
}
const testStrings = ['test1', 'test2', 'test3']
console.log(firstString(testStrings))
// -> 'test1'

/**
 * 数値の配列を受け取って一つ目の数値を返す
 */
const firstNumber = (arr: number[]): number => {
  return arr[0]
}
const testNumbers = [10, 20, 30]
console.log(firstNumber(testNumbers))
// -> 10

上記の関数だとそれぞれ文字列(string)と数値(number)に対応した関数になっているので、使いまわすことができません。
このような場合にジェネリクスを使うことで汎用的な関数を作成することが可能になります。

/**
 * 配列を受け取り一つ目の要素を返す
 */
const firstElement = <T>(arr: T[]): T => {
  return arr[0]
}

const testStrings = ['test1', 'test2', 'test3']
const testNumbers = [10, 20, 30]

console.log(firstElement<string>(testStrings))
console.log(firstElement<number>(testNumbers))

このように抽象化して対応する型に対して引数のような型を与えることが出来ます。

関数型のガイドライン

こちらは公式ドキュメントにガイドラインとして記載されている内容になります。
要は、これはやるなよ、危険だから。ってことですね。

  • Push Type Parameters Down

Documentation - More on Functions Learn about how Functions work in TypeScript.

  • Use Fewer Type Parameters

Documentation - More on Functions Learn about how Functions work in TypeScript.

  • Type Parameters Should Appear Twice

Documentation - More on Functions Learn about how Functions work in TypeScript.
上記リンクの内のソースと解説が書いてありますが、関数型の場合は下記に該当しないか注意する必要があります。

  1. extendsでany型をあてるんじゃあない
  2. 意味のない型引数をあてるんじゃあない
  3. 複数回出てこない(対応関連していない)場合はジェネリクスを使うんじゃあない

その他

その他にも下記のような話題が出ていました。
その他のディスカッション一例

  • Constructorの型指定に初期化子を付与
  • 引数のオプショナルパラメーター
  • コールバック関数内のオプショナルパラメーター

上記は一例になりますが、今回の勉強会はジェネリクスの会話が多く、特徴やユースケースについての議論が多かったので今回のまとめはこの辺りにします。

さいごに

う〜ん。徐々にレベルが上がってきましたねぇ。
ジェネリクスは便利ですが、抽象化と共通化が出来ないと使いこなせないので、実際のユースケースとセットで学んでいかないとダメっぽいですね。
次回も関数の型制御について学んでいくのですが、一段レベルが上がるので参加者全員で理解度を上げていこうと思います!
以上!最後までご覧くださりありがとうございました!