Utility Types とは
type User = {
name: string;
age: number;
address: string;
phoneNumber: string;
};
type PartialUser = Partial<User>;
// PartialUserの型
PartialUser = {
name?: string;
age?: number;
address?: string;
phoneNumber?: string;
};
上記の例のように、Utility Types
とはコード内で型変換を簡単にしてくれます。
ただ、phoneNumber
のみオプショナルにしたいとき、それに相当するUtility Types
は存在しないので、組み合わせて作ってみます。
自作 UtilityTypes を作る
Partial
、Pick
とOmit
を組み合わせて作ります。
type customPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
実際の使い方は以下のようになります。
type User = {
name: string;
age: number;
address: string;
phoneNumber: string;
};
type PartialUser = customPartial<User, 'phoneNumber'>;
// PartialUserの型
PartialUser = {
name: string;
age: number;
address: string;
phoneNumber?: string;
};
// phoneNumberはオプショナルなのでなくても良い
const user: PartialUser = {
name: 'hoge',
age: 20,
address: 'fuga',
};
解説
type customPartial<T, K extends keyof T>
の部分から見ていきます。
T は User が入ります。keyof T
はname
、age
、address
、phoneNumber
の 4 つの文字列の Union 型になります。つまり、K
はname
、age
、address
、phoneNumber
のいずれかの文字列になります。
次に、Omit
の部分です。
Omit<T, K>;
Omit はT
からK
を除外した型を返します。
例えば
type User = {
name: string;
age: number;
address: string;
phoneNumber: string;
};
type OmitUser = Omit<User, 'name' | 'age'>;
のようにすると、OmitUser
の型は
OmitUser = {
address: string;
phoneNumber: string;
}
となります。
次に、Partial
とPick
の部分です。
Partial<Pick<T, K>>;
Partial
はT
の全てのプロパティをオプショナルにします。Pick
はT
からK
を選択した型を返します。
そして選択された型をPartial
でオプショナルにします。
例えば
type User = {
name: string;
age: number;
address: string;
phoneNumber: string;
};
type PickAndPartialUser = Partial<Pick<User, 'name' | 'age'>>;
のようにすると、PartialUser
の型は
type PickAndPartialUser = {
name?: string;
age?: number;
};
となります。
最後にこれらを組み合わせると、
type PartialUser = {
name?: string;
age?: number;
address: string;
phoneNumber: string;
};
となります。
これにて utilitytypes のハック完了です。
オプショナルをとるパターン
逆に必須にしるパターンも作ってみます。
type customRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
同じ考えでできますね。
GitHubで編集を提案
Discussion