カルキチブログ

よく使う・使用頻度の高そうなTypeScriptのUtility Typesについてまとめてみた

だいぶ時間空きましたが、久しぶりに書いてみました。

今回はTypeScriptのUtility Typesについてです。

趣味レベルで書いていた時は、とっつきづらいこともあってほぼ使った経験がなかったのですが、実務でTypeScriptを書くようになってからは、必要性を感じてきたので、よく使用するようになりました。

今回はよく使うUtility Typesと使ったことないけど、便利そうだなと感じているUtility Typesについて記事を書いてみました。

TypeScriptのUtility Typesとは?

TypeScriptのUtility Typesとは、TypeScriptが提供する便利な型のことです。

既存の型の一部のみを使用した新しい型を生成したいときに役に立ちます。

うまく利用できれば、いちいち関数の引数やpropsごとに型定義をする手間を解消してくれます。

TypeScriptの公式サイトを確認してみたのですが、Type Scriptには多種多様なUtility Typesがあります。

https://www.typescriptlang.org/docs/handbook/utility-types.html

→本筋からちょっと逸れるのですが、TypeScriptの公式サイトはGatsbyで作られてるっぽいですね!

Pick<T, K>・Omit<T, K>

Pick<T, K>既に存在する型から特定の要素のみを抽出した新しい型を生成することができる型です。

単純明快でわかりやすく、便利な型なので使用頻度は多い気がします。

type User = {
  id: number;
  name: string;
  age: number;
  email: string;
};

type UserNameAndAgeType = Pick<User, 'name' | 'age'>;

新しく生成される型

type UserNameAndAgeType = {
  name: string;
  age: number;
};

上記のサンプルコードは、ユーザー情報を持っているオブジェクトからnameとageのキーを持つオブジェクトの型を新しく生成する例です。

Omit<T, K>と呼ばれるUtility Typesを使用すると、Pickとは逆のこと(第2ジェネリクスで指定したキーを除外した型を新しく生成)ができます。

type User = {
  id: number;
  name: string;
  age: number;
  email: string;
};

type OmitSampleType = Omit<User, 'age' | 'email'>;

新しく生成される型

type OmitSampleType = {
  id: number;
  name: string;
};

Readonly<T>

Readonly<T>は、全てのプロパティを読み取り専用することができます。

下記のソースコードの場合、Readonly型を付与したblogPostというオブジェクトは直接値を変更することができなくなります。

interface BlogPost {
  title: string
  body: string;
  description: string;
};

const blogPost: Readonly<BlogPost> = {
  title: '家の掃除',
  body: '本文',
  description: '記事の概要',
}

// [tsserver 2540] [E] Cannot assign to 'title' because it is a read-only property.
blogPost.title = '';

TypeScriptでは、constアサーションを利用したやり方でも値を読み取り専用にすることができますね!

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions

ReturnType<T>

ReturnType<T>は、関数の戻り値を返すことができる型です。

ReduxやVue3のprovide・injectなどのステート管理のロジックをTypeScriptで書いてるとお世話になります。

使用頻度自体は高くもなく、低くもなくって感じです。

type User = {
  id: number;
  name: string;
  age: number;
  email: string;
};

const getUserInfo = (user: User) => {
  return {
    name: user.name,
    age: user.age,
  }
};

type FuncType = ReturnType<typeof getUserInfo>;

新しく生成される型

type FuncType = {
  name: string;
  age: number;
};

Partial<T>・Required<T>

Partical<T>全てのプロパティの型をオプショナルにすることができる型です。

オプショナルとは『任意の』という意味なので、必ずしも持っておく必要がない状態にすることができるようになります。

type User = {
  id: number;
  name: string;
  age: number;
  email: string;
};

type UserOptionalType = Partial<User>;

新しく生成される型

type UserOptionalType = {
  id?: number;
  name?: string;
  age?: number;
  email?: string;
};

必ずしも持っておく必要がない状態の型を作り出すことができるので、以下のような定数を定義することが可能になります。

type User = {
  id: number;
  name: string;
  age: number;
  email: string;
};

// オプショナルじゃないとエラーが発生する
const user: Partial<User> = {
  name: 'Karukichi',
};

Required<T>はオプショナルの逆の動き、つまり、全てのプロパティを必須にすることができるようになります。

type User = {
  id: number;
  name: string;
  age?: number;
  email?: string;
};

type UserRequiredType = Required<User>;

新しく生成される型

type UserRequiredType = {
  id: number;
  name: string;
  age: number;
  email: string;
};

Extract<T, U>・Exclude<T, U>

Extract<T, U>Exclude<T, U>は、指定した型から要素を抽出、除外した型を作ることができる型です。

Pick<T, K>やOmit<T, K>と似ているようですが、こちらは主に共用体型に使用されることが多いらしいです。

Extract<T, U>の場合は、第2ジェネリクスUに指定した型を残した型を生成することができます。

type ButtonTypes = 'small' | 'medium' | 'large' | 'super-big';

type SmallButtonType = Extract<ButtonTypes, 'small'>;

プリミティブ型を直接指定することができるので、以下のような記述もできます。

type Types = 'small' | 'medium' | 'large' | 'super-big' | 1 | true;

type ButtonType = Extract<Types, string>;

新しく生成される型

type SmallButtonType = 'small'

type ButtonType = "small" | "medium" | "large" | "super-big"

Exclude<T, U>は、Extract<T, U>とは逆に第2ジェネリクスUに指定した型を除外した型を生成することができます。

type ButtonTypes = 'small' | 'medium' | 'large' | 'super-big';
type SmallButtonType = Exclude<ButtonTypes, 'small'>;

type Types = 'small' | 'medium' | 'large' | 'super-big' | 1 | true;
type ButtonType = Exclude<Types, string>;

新しく生成される型

type SmallButtonType = "medium" | "large" | "super-big"

type ButtonType = true | 1;

まとめ

まとめます。

  • TypeScriptのUtility Typesとは、TypeScriptが提供する便利な型のこと
  • 既存の型から必要なものだけ抽出・除外した型を生成することができる
  • プロパティの指定を必須にするかオプショナルにするかの変更を行うこともできる

Utility Typesをうまく利用して望んだ型が生成できるようになると、TypeScriptはもっと楽しくなります。

おまけ

最近めちゃクソ忙しくて月1更新が途絶えてしまいました。

まあ何回か途絶えさせてはいますが、2ヶ月は過去最長だったような気がします。

忙しい中でも情報発信はやっていかないとなー、、、と思っている今日この頃です。