初めに
こちらの記事はgenericsについて調べてみたち、使ってみたりという自分の備忘録です。
genericsとは
型を引数で渡すことができるというもの
function func<T>(value: T) {
return value;
}
func<string>("hello") // hello
func<number>(1) // 1
func<{ name: string }>({ name: "keisei" }) // { name: 'keisei' }
ちなみに関数を実行をする時に型を指定しなかった場合は勝手に注釈してくれます。
function func<T>(value: T) {
return value;
}
func("hello") // hello
func(1) // 1
func({ name: "keisei"}) // { name: 'keisei' }
extendsを使って型に制約をつけてみた
// extendsを使って呼び出し時にnameを必ずつけないといけないようになる。
function func<T extends { name: string }>(value: T) {
return value.name;
}
func({ name: "名前", age: 10 }) // OK!
下記はコンパイルエラーになる。
function func<T extends { name: string }>(value: T) {
return value.name;
}
func({ age: 10 }) // NG!
keyofを使ってみる
// 型引数の『U』の部分でkeyofを使ってオブジェクトのキーをユニオン型にする // key: "namge" | "age" となる。
type TUser = { name: string, age: number }
function getValue<T extends TUser, U extends keyof T>(user: T, key: U) {
return user[key]
}
const user = {
name: "tanaka",
age: 20,
}
console.log(getValue(user, "name")) // 第二引数は "name" か "age" しか受け付けない。
アウトプット
ジェネリクスでユーザーの型を選択してみた。
おそらくこんな感じで使うだろうと思っている。
type TUser = {
name: string,
age: number
}
// 前提:好きなゲームにどのようなユーザーでログインをするかという事を想定している。。
type TAppUser<T> = {
name: string;
loginUser: T
}
type TAdminUser = TUser & {
role: string,
status: string
}
const normalApp: TAppUser<TUser> = { // ストリートファイターを通常のユーザーでやりたい
name: "ストリートファイター",
loginUser: {
name: "kekek",
age: 1
}
}
const adminApp: TAppUser<TAdminUser> = { // サモンナイトを管理ユーザーでやりたい
name: "サモンナイト",
loginUser: {
name: "kekek",
age: 1,
role: "super",
status: "fine"
}
}
Utilityで個人的に失念しそうだが使えそうと思っているもの
名前 | 使いどころ |
---|---|
Pick | 指定した型を追加した新たな型を構築 |
Omit | 指定した型を除去した新たな型を構築 |
Exclude | 割り当て可能な型を除外することにより、キー名を使った新たなユニオン型を構築 |
Extract | Excludeの反対、共通する型に絞り込んだ、キー名を使った新たなユニオン型を構築 |