Typescriptでジェネリックを活用する
Author: 水卜
Author: 水卜
ジェネリックとは、型を抽象化する機構を指す。
Typescriptでは、型引数を使用して、どんな型でも受け取れる関数やクラスを実現することができる。
例えば、TypescriptにはPartialという型がある。
type Partial<T>
Partialは与えられた型の全てのプロパティを省略可能にした、新しい型を返す。
<T>
が型引数で、任意の型を渡せる。Tはジェネリック型とも呼ばれる。
下記のようなサンプルを書いてみた。
interface User {
firstName: string
lastName: string
email: string
isAdmin: boolean
}
const createUser = (properties: Partial<User>) => {
const _default = <T> (value: T, default: T): T => {
return value === undefined ? default : value
}
return {
firstName: _default(properties.firstName, 'TEST'),
lastName: _default(properties.lastName, 'TEST'),
email: _default(properties.email, 'test@test.com'),
isAdmin: _default(properties.isAdmin, false)
}
}
createUserで新しいUserを作成することができる。
createUserの引数はPartial<User>
なので、Userのプロパティを全て渡す必要はない。emailの部分だけテストしたいときはemailだけ渡せばいい。
_default
は、引数として渡されたPartial<User>
にプロパティがなかったら第二引数のデフォルト値を返す関数。
これにより、最低限のプロパティでユーザーを量産できるようになった。
ジェネリックでなんでもできるというわけではなく、下記のような場合はコンパイルエラーになる。
interface User {
login()
}
const login => <T> (cls: T) => {
cls.login()
}
Tがlogin()
関数を持っているかどうか分からないためにエラーが起こる。
このような場合は以下のようにジェネリックに制約を与える。
const login => <T extends User> (cls: T) => {
cls.login()
}
これでTがUserまたは、Userを継承したクラスであることをコンパイラに明示できる。