🚀

TypeScript Utility Typesについてとその活用一例

2022/03/20に公開

そもそもTypeScriptのUtility Typesとは何か?

TypeScript側が用意してくれている便利な型の定義です。
JavaScript等に元々備わっている組み込み関数の型版ですね。
色々あるようですので調べてみると面白いかと思います。

今回は個人的に使用頻度の高いPartial,Required,Pick,Omitについてと活用した一例を紹介したいと思います。活用例では自作の型定義も使用します。

全体で使用する型定義

type Content = {
  id?:string;
  title:string;
  status: '完了' | '未完' | '途中';
  summary?: string[];
};

Partial <T>

Tの全てのプロパティをオプショナル化してくれます。

type PartialContent = Partial<Content>;
// 型推論
type PartialContent = {
    id?: string | undefined;
    title?: string | undefined;
    status?: "完了" | "未完" | "途中" | undefined;
    summary?: string[] | undefined;
};

このような感じで全てに?が付くのでそれぞれのプロパティが存在しなくてもよくなります。

const myContent:PartialContent = {
  title:"hogehoge";
};

titleしか存在しない場合でも怒られなくなります。

Required <T>

Partialの逆になります。全てのプロパティを必須にしてくれます。絶対欲しいねん!ってやつです。

type RequiredContent = Required<Content>;
//型推論
type RequiredContent = {
    id: string;
    title: string;
    status: '完了' | '未完' | '途中';
    summary: string[];
};

Pick <T,K>

これは直感的にわかりやすい単語でした。T型の中からKを抽出した(pick up)した新しい型を作成してくれます。

type ContentTitleSummary = Pick<Content,'title' | 'summary'>;
//型推論
type ContentTitleSummary = {
    title: string;
    summary?: string[] | undefined;
};

Omit <T,K>

この流れから察する通りPickの逆、つまりT型の中からKを除外した新しい型を作成してくれます。

type ContentExcludeTitleSummary = Omit<Content, 'title' | 'summary'>;
//型推論
type ContentExcludeTitleSummary = {
    id?: string | undefined;
    status: '完了' | '未完' | '途中';
}

最後に自作の型定義と組み合わせて使用した一例

狙いとしてtype Contentで定義されたsummaryの型定義 である

string[]

のみを抽出して新たな型として使用します。オプショナルも解除します。

まずはプロパティのvalueのみを抽出する自作の型を用意する。

(自作と言いつつ他の方の物を拝借しています)

type ValueOf<T> = T[keyof T];

これでT型の中からvalueのみを抽出する型ができました。

次はこのTに当たる型を用意する。

使用するのは型の一部を抽出する為のPickとオプショナル化されているものを必須化するRequiredとなります。

type RequiredPick = Required<Pick<Content,'summary'>>;
//型推論
type RequiredPick = {
    summary: string[];
}

あとはこの型定義を組み合わせると完成となります!

type ContentSummary = ValueOf<RequiredPick>;
//型推論
type ContentSummary = string[];

//このようにも書けます
type ContentSummary = ValueOf<Required<Pick<Content, 'summary'>>>;

おまけ

mapped typesなるものも存在します。詳しい説明は出来ないので省きますが、関数のような感じで型の定義(制約)ができるようです。

Partialと同じものをmapped typesで用意するとこのようになります。

type Concrete<T> = {
  [P in keyof T]-?: T[P];
};

T型に入れた型のキーから?が取り除かれる。つまりPartialと同じ事が出来ています。

この辺をもっときちんと使える日が来れば型上級者になれること間違いなしです!

Discussion