[TypeScript]Requiredについて、実際に実装して理解する。


TypeScriptの既存の型から全てのプロパティを必須にして新たな型にするRequiredというものがある。
今回はこれを自力で実装しながらRequiredについて理解することを目的とする。

Requiredとは

Requiredとは以下の書式を持つ組み込み型で、ジェネリクスに指定したプロパティの全てを必須にしてくれるものです。
なお、Requiredではネストされたプロパティについては必須には出来ません。

// Required<T> Tに指定された型のキーを全て必須にする。
type User = {
id: number
name: String
profile?: String
}
type RequiredUser = Required<User>
// type RequiredUser = {
// id: number;
// name: String;
// profile: String;
// }

今回はこれを実装して理解していきます。
すなわち以下のMyRequiredを実装していきます。

type RequiredUser = MyRequired<User>
// type RequiredUser = {
// id: number;
// name: String;
// profile: String;
// }

MyRequiredの実装方針

MyRequiredを実装するにあたって、以下の方針で段階を踏んで実装していきます。

  1. MyRequired<T>に指定されたプロパティのキーを羅列する
  2. それぞれのキーに対して、Tの型を設定する

では順に見ていきましょう

MyRequiredに指定されたキーを羅列する

プロパティのキーを羅列するにはkeyofを使用します。
そのため、Tのキーを羅列するには以下のようにすることで可能です。

type keys = keyof T
// 例
type UserKeys = keyof User
// type Userkeys = "id" | "name" | "profile"

ただ、これだけではキーを羅列しただけで、キーに対する方を設定することが出来ません。
次にこの型を設定していきます。

それぞれのプロパティのキーに対して、Tの型を設定する。

TypeScriptにはMapped Typesと呼ばれる、元の型に基づいて新しい型を作成可能な仕組みがあります。
これを用いて、Tの型を設定していきます。
以下はMapped Typesを用いて、Userのプロパティのキー全てに対してStringを設定した例です。

type MyRequired<T> = {
[K in keyof T]: String
}
type my = MyRequired<User>
// type my = {
// id: String;
// name: String;
// profile: String;
// }

このStringの部分を元のプロパティの型に設定してあげれば良さそうですね。
これは以下のようにすることで可能です。

type MyRequired<T> = {
[K in keyof T]: T[K]
}
type my = MyRequired<User>
// type my = {
// id: number;
// name: String;
// profile: String;
// }

まとめ

今回はRequiredの実装を順を追って実装していきました。
理解出来ましたでしょうか?
簡単な手順なので理解出来たのでは無いでしょうか。

順を追うとtypescriptに不慣れな人でも実装できると思います。
このように簡単な作業に分解することでこのようなものでなく、色々な問題も解決できるのでぜひ