TypescriptのOmitで複数のプロパティを除外する時に、
Omit<Omit<HOGE,"fuga">,"piyo">
というような恰好悪いことをやっていたのですが、
全然意味を理解していなかったことを痛感したので備忘を兼ねて
正しいやり方
Omit<HOGE,"fuga" | "piyo">
複数のフィールドを除外したい場合は、それらのプロパティ名をUnion型で渡してやればOK。
原理
Omitの定義をたどると、
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
となります。
この時重要なのがkeyof
で、これは後に続く型のプロパティ名をUnion型で返します。
Omitの場合anyなのでstringがnumberかsymbolで構成されたUnion型ならOKです。
このため、上記の正しいやり方で示した "fuga"|"piyo"
のように複数のプロパティ名をを渡すことが可能です。
Kがどう扱われるのか
その後の定義を見ていくと、Exclude<keyof T,K>
しています。
ここでT全体のpropertyを列挙したUNION型からKで指定したものを抜くわけです。
さらに、得られた残りのプロパティ名の集合(UNION型)をPickに渡しています。
Pickも似たような形で、 K extends keyof T
という形で第二型引数を受けているので、UNION型を渡せます。
Pickの中身
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Pickの定義は上記の通り。
Kに含まれるプロパティPの方はTにPでアクセスしたときのものと同じという意味。
仕組み的には以下と同じ。
type HOGE = {
[fuga:number]:string
}
type s = HOGE[number]//s はstring
このような型定義をしているため、PickのKは extends keyof Tでなければならないわけですね。
まとめ
- OmitやPickに複数指定したい時はUnion型で渡す
- keyofはプロパティをUnion型で返す