以下のようなコードがあったとき、
class Human { constructor(public name: string){} SayHello(){ console.log(`こんにちは。私の名前は${this.name}です。`) } } const yamada = new Human("山田") yamada.SayHello()
Human
から{ name: string }
という型をつくりたいとします。
ですが、SayHello
は型に含めたくないとします。
こうときは、以下のようにPick
などで個別のメンバを指定することで実現できます
Pick<Human, "name">
Exclude<Human, "SayHello">
ただ、これだとメンバが増えたときにいちいち修正しないといけないので面倒くさいです。
なのでそういうときは以下のようなコードを書いて、
type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]; export type ExcludeMethods<T> = Pick<T, NonFunctionPropertyNames<T>>;
ExcludeMethods
を使ってtype HumanProfile = ExcludeMethods<Human>
と書くと、メソッドだけを除いた型を作れます👇
ちなみに何故これがしたかったかというと、Firebase FireStoreで以下のようにclassのインスタンスを保存しようとすると「プリミティブなオブジェクトしか受け付けへんで」的なエラーが出たからです。
class Human { constructor(public name: string){} SayHello(){ console.log(`こんにちは。私の名前は${this.name}です。`) } } const yamada = new Human("山田") const docRef = doc("collection", "id"); await setDoc(docRef, yamada); //❌これはダメらしい
以下のような感じにすると行けました。
class Human { constructor(public name: string){} SayHello(){ console.log(`こんにちは。私の名前は${this.name}です。`) } GetPrimitive(): HumanProfile{ return {...this} } } const yamada = new Human("山田") const docRef = doc("collection", "id"); await setDoc(docRef, yamada.GetPrimitive());//✅これだと行ける
なんか「もっとスマートにできないの?」感はありますが、他に方法が思いつきませんでした。。
というかそもそも、なんでclassのインスタンスをそのまま保存できるようになってないんだろう。めちゃ不便じゃね・・?
おわり
参考:
How to create a type excluding instance methods from a class in typescript? – Stack Overflow
angular – Firestore: Add Custom Object to db – Stack Overflow
コメント