Recordの使いどころ
Recordについて調べたので書く
最小サンプル
//Record<K,T>
type SmallRecord = Record< "a"|"b"|"c" , string >
SmallRecord は以下の型として展開される
// SmallRecord
{
a : string,
b : string,
c : string
}
つまり Kに列挙された型がプロパティになり、それぞれTを持つオブジェクト型になる。
サンプルコード
以下のようなオブジェクトがある。
const users = {
"suzuki" : {
age : 26,
name : "suzuki"
},
"sato" : {
name : "sato",
age : 32
},
"takahashi" : {
name : "takahashi",
age : 40,
},
"tanaka" : {
name : "tanaka",
age : 25,
}
}
上のオブジェトを下記の形へ変形させる 関数を考える
{
"suzuki" :26,
"sato" : 32,
"takahashi" : 40,
"tanaka" :25
)
素直に書くとこんな感じでしょうか?
const usersAgeFn1 = (users:{[key:string] : {age:number}}) => {
let ages : {[key:string]:number} = {}
for( let [key,value] of Object.entries(users) ){
ages[key] = value.age
}
return ages
}
const usersAge1 = usersAgeFn1(users)
別に上でも悪くないが、戻り値の型は {[key:string]:number}になり、プロパティが維持できない。(コード補完が効かない)
RecordとGenericsを併用して書く
※ asが多いが許して
const usersAgeFn2 = <T extends {[key:string]:{age:number}}>(users:T) => {
let ages = {} as Record<keyof T , number>
for( let [key,value] of Object.entries(users) ){
ages[key as keyof T] = value.age
}
return ages
}
const usersAge2 = usersAgeFn2(users)
これで戻り値の型はプロパティを維持した状態になる(コードの補完が効く)
Mapped Types でも同じ事はできる。
サンプルのコードだとこっちの方がシンプルに見えるかもしれない。
const usersAgeFn3 = <T extends {[key:string]:{age:number}}>(users:T) => {
let ages = {} as {[P in keyof T]:number}
for( let [key,value] of Object.entries(users) ){
ages[key as keyof T] = value.age
}
return ages
}
const usersAge3 = usersAgeFn3(users)