🦍
【TypeScript】Utility Types ハックして自作の型を作ってみた
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