【2022年保存版】よく使うUtility Typesまとめ

# TD;LR
最初に、本記事で紹介するUtility Typesの概要をお伝えします。細かい説明は各セクションにコード付きで書いてありますのでご覧ください。
- `Readonly<Type>`
    - 読み取り専用にします
- `Partial<Type>`
    - プロパティを任意項目にします
- `Required<Type>`
    - プロパティを必須項目にします
- `Pick<Type, Keys>`
    - Keysで指定した型を抽出します
- `Omit<Type, Keys>`
    - Keysで指定した型「以外」を抽出します
- `Extract<Type, Union>`
    - UnionTypeに対してExcludedMembersで指定した型を抽出します
- `Exclude<UnionType, ExcludedMembers>`
    - UnionTypeに対してExcludedMembersで指定した型「以外」を抽出します
- `NonNullable<Type>`
    - null, undefinedを除外します
- `Parameters<Type>`
    - 関数の引数の型を返します
- `ReturnType<Type>`
    - 関数の戻り値の型を返します


# Utility Typesとは
公式Documentでは以下のように書かれています。要約すると、「Utility Typesを使うとTypeScriptの型変換を簡単にできるよ」ということです。
> TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.

# `Readonly<Type>`
Typeに指定した全てのプロパティを読み取り専用にします

```diff_typescript
type User = {
  name: string;
  age: number | null;
  country?: "US" | "UK" | "JP";
};

+ const user: Readonly<User> = {
  name: 'taro',
  age: 32,
};

// エラー：　Cannot assign to 'name' because it is a read-only property.
// user.nameは読み取り専用なので上書きすることはできません
user.name = 'hanako';
```
# `Partial<Type>`
Typeに指定した全てのプロパティをOptional(任意）にします
```diff_typescript
type User = {
  name: string;
  age: number | null;
  country?: "US" | "UK" | "JP";
};

// 全てのプロパティが任意項目となったためどちらもOK
+ const user1: Partial<User> = {};
+ const user2: Partial<User> = {
+   name: 'hanako',
+ };
```
# `Required<Type>`
Typeに指定した全てのプロパティを必須にします
```diff_typescript
type User = {
  name: string;
  age: number | null;
  country?: "US" | "UK" | "JP";
};

// 全てのプロパティが必須項目なので元々任意だったcountryも指定する必要がある
+ const user: Required<User> = {
  name: 'taro',
  age: 32,
  country: 'JP',
};
```

# `Pick<Type, Keys>`
Typeの中からKeysで選択したプロパティの型をピックアップします
```diff_typescript
type User = {
  name: string;
  age: number | null;
  country?: "US" | "UK" | "JP";
};

// Userから'name'と'country'をピックアップする。'age'を指定するとエラーになる。
+ const user: Pick<User, 'name' | 'country'> = {
  name: 'taro',
  country: 'JP',
};
```

# `Omit<Type, Keys>`
Typeの中からKeysで選択したプロパティの型を「以外」ピックアップします
```diff_typescript
type User = {
  name: string;
  age: number | null;
  country?: "US" | "UK" | "JP";
};

// Userから'age'「以外」をピックアップする。'age'を指定するとエラーになる。
+ const user: Omit<User, 'age'> = {
  name: 'taro',
  country: 'JP',
};
```
# `Extract<Type, Union>`
Excludeとは逆でUnionTypeに対してExcludedMembers型を指定する
```diff_typescript
type Primitive = string | number | boolean

// OK
const value1: Extract<Primitive, string> = 'aaa';

// NG :string型は指定していないのでエラー
const value2: Extract<Primitive, number | boolean> = 'aaa';
```

# `Exclude<UnionType, ExcludedMembers>`
UnionTypeに対してExcludedMembersで指定した型を除外します
```diff_typescript
type Primitive = string | number | boolean

// OK
const value1: Exclude<Primitive, string> = true;

// NG
　// stringを除外しているので指定できない
const value2: Exclude<Primitive, string> = 'aaa';
```
# `NonNullable<Type>`
指定したTypeから`null`と`undefined`を取り除きます
```diff_typescript
type UserA = <string | boolean | undefined> // string | boolean
type UserB = <string | null | undefined> // string
```
# `Parameters<Type>`
関数の引数の型をタプル型として返します
```diff_typescript
const func = (num: number, isLoading: boolean, value: string) => {
    return ...
};

// [number, boolean, string]
const funcType: Parameters<typeof func> = [1234, true, 'aaaa'];
```
# `ReturnType<Type>`
関数の戻り値の型を返します
```diff_typescript
const func = (): string => {
    return 'aaa'
};

// string型
const funcType: ReturnType<typeof func> = 'bbb';
```


# 参考文献
https://www.typescriptlang.org/docs/handbook/utility-types.html