何がしたいか?
TypeScriptにおいて、とある型の一部のプロパティのみを必須にした型を作りたいとします。
次の例で言うと、とある型(User)を元に、一部のプロパティ(age)を必須にした新たな型(AdultUser)を作りたいとします。
type User = { name: string mail: string age?: number phone?: string } // 成人のユーザーの年齢プロパティは必須 type AdultUser = { name: string mail: string age: number phone?: string } // ageがundefinedになっていることを防ぎたい const adult: AdultUser = { name: 'テスト太郎', mail: 'test@example.com' } // 次のエラーが発生する // Property 'age' is missing in type '{ name: string; mail: string; }' but required in type 'AdultUser'.
上記の例の場合はプロパティの数が少なかったので良かったですが、実際はもっと項目が多かったり、Userのプロパティが頻繁に変更されるとミスが出てくると思います。
今回はそのために簡単な型エイリアスを作りましたので、紹介したいと思います。
どんな型エイリアス?
type SomeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
Utility Typesを使いました。
Utility Typesについては公式のドキュメントを読んでください。
www.typescriptlang.org
新たに定義したSomeRequiredを使うと、次のようにAdultUser型を定義することができます。
type AdultUser = SomeRequired<User, 'age'> const adult: AdultUser = { name: 'テスト太郎', mail: 'test@example.com' } // 次のエラーが発生する // Type '{ name: string; mail: string; }' is not assignable to type 'AdultUser'. // Property 'age' is missing in type '{ name: string; mail: string; }' but required in type 'Required<Pick<User, "age">>'.
また、Omit
や Pick
と同様に、|
を使うことで複数の項目を必須にすることができます。
type NewAdultUser = SomeRequired<User, 'age' | 'phone'> const newAdult: NewAdultUser = { name: 'テスト太郎', mail: 'test@example.com', } // Type '{ name: string; mail: string; }' is not assignable to type 'NewAdultUser'. // Type '{ name: string; mail: string; }' is missing the following properties from type 'Required<Pick<User, "age" | "phone">>': age, phone
終わりに
Utility typesを知っている方なら簡単にわかる型エイリアスだと思いますが、知らなかった方は是非使ってみてください!