📖

【TS初級から中級へ】ジェネリクスで処理をまとめてスッキリ

に公開

なかなか理解が難しいTypeScriptのジェネリクス。特にプログラミングを始めたての頃は、なんかよくわかんないし、何に使うのかいまいちイメージができません。

でも、ジェネリクスを使いこなせるとかっこいいですよね。初級から中級になった感じがします。

実際に使えるようになるとすごく便利でコードもスッキリします。
詳しい説明はサバイバルTypeScriptにゆずるとして、簡単に、どんなふうに使えるの?というのを紹介します。

似たような処理をまとめる

ジェネリクスのいいところは、似たような処理を1つにまとめてスッキリさせるところです。

並び替えの処理を例にしましょう。アプリのユーザーを特定の条件で並べ替えするとします。

ユーザーには種類があり、「一般ユーザー(NormalUser)」と「特別なユーザー(SpecialUser)」があったとします。
型にするとこんな感じです。

type NormalUser = {
  id: number
  name: string
  createdAt: string
  userType: "normal" | "special"
}
  
type SpecialUser = {
  id: number
  name: string
  createdAt: string
  userType: "normal" | "special"
  job: string
  followers: string[]
} 

このユーザーを、idnamecreatedAtで並べ替えます。3つの方法を比べてみましょう。

(1)処理を2つ書く

単純に考えると、別々の処理を書きたくなってしまいます。なぜなら型が違うから。

const sortNormalUser = (users: NormalUser[]) => {
  // id、name、createdAtでの並び替え処理
}

const sortSpecialUser = (users: SpecialUser[]) => {
  // id、name、createdAtでの並び替え処理
}

しかし、これだとNormalUserSpecialUserを混ぜて並び替えたい時は使えませんよね。

(2)ユニオン型を使う

次はユニオン型を使う方法です。

const sortUser = (users: (NormalUser | SpecialUser)[]) => {
  // id、name、createdAtでの並び替え処理
}

うまく行きそうです。

が、新しいユーザー型(TemporalyUser)が増えた場合はどうでしょう?
sortUser()の引数の型に追加すれば良いだけですが、今後ユーザー型が増えるたびに追加するのは面倒です。

(3)ジェネリクスを使う

受け取る引数の型がなんであれ、並び替えに使うのはidnamecreatedAtの3つだけです。
この3つを持つ型ならなんでもOKにしたいですよね!

そこで使えるのがジェネリクスです。まずは並び替えに必要な情報だけを持った型SortableUserを宣言します。

type SortableUser = {
  id: number
  name: string
  createdAt: number
}

以下のsortUser()では、SortableUserをextendsした型ならなんでも受け入れます。つまり、idnamecreatedAtがあるオブジェクトならなんでもこの関数につっこんで並び替えできるんです。

type SortableUser = {
  id: number
  name: string
  createdAt: number
}

const sortUser = <T extends SortableUser>(users: T[]) => {
  // id、name、createdAtでの並び替え処理
}

const users = [
  {id: 1, name: "普通のユーザー", createdAt: 1, userType: "normal"},
  {id: 2, name: "特別なユーザー", createdAt: 2, userType: "special", job: "programmer", followers: [1]},
  {id: 3, name: "一時ユーザー", createdAt: 3, userType: "temp", expiredAt: 3}
]

const sorted = sortUser(users)

これなら既存のsortUser()の修正は最低限に、柔軟な関数を実装できます!

まとめ

使えるようになるまではジェネリクスっていつ使うの?とか、ほんとに便利なの??と思っていました。が、使えるようになるとスマートなコードを書けるようになり、エンジニアとしてレベルが上がった感じもします。

一緒にスマートなコードを書けるよう精進していきましょう!

Discussion