2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptにおいて、「型」は非常に重要な概念です。今回は、型をよりスマートに効率的に書くための Mapped Typesユーティリティ型 について扱おうと思います。

1. Mapped Typesとは?

Mapped Types とは、既存の型を基にして、新しい型を作成する仕組み です。これは、オブジェクトのプロパティを動的に変換する際に便利です。

例えば、すべてのプロパティを readonly にしたい場合、通常はこのように記述すると思います。

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

type ReadonlyUser = {
  readonly id: number;
  readonly name: string;
  readonly email: string;
}

Userのプロパティが今は3つですが、これが10, 20個と増えた際にすべてにreadonlyをつけるのは少し冗長で見映えが悪いです。
Mapped Types を使った場合、以下のようにより簡潔に記述できます。

type ReadonlyUser = {
  readonly [K in keyof User]: User[K];
}

これで先ほどと同様、 User 型のすべてのプロパティが readonly になりました。


2. 基本のMapped Types

1. すべてのプロパティをオプショナルにする (Partial<T>)

type PartialUser = {
  [K in keyof User]?: User[K]
}

ユースケース

  • 一部のデータのみ更新したい時
  • フォームの入力値を部分的に扱いたい時

2. すべてのプロパティを必須にする (Required<T>)

type RequiredUser = {
  [K in keyof User]-?: User[K]
}

ユースケース

  • APIのレスポンスで全データが必ず存在する場合

3. すべてのプロパティを readonly にする (Readonly<T>)

type ReadonlyUser = {
  readonly [K in keyof User]: User[K]
}

ユースケース

  • オブジェクトの変更を防ぎたい時(Reactのprops など)

3. TypeScriptのユーティリティ型を活用しよう!

TypeScriptには、開発を効率化する 便利なユーティリティ型 が色々用意されています。

1. Pick<T, K> : 指定したプロパティだけを抽出

// Userからidとnameプロパティだけを抽出
type PickUser = Pick<User, "id" | "name">

ユースケース

  • APIレスポンスで必要なプロパティだけを取得

2. Omit<T, K> : 指定したプロパティを除外

// Userのうちemail以外のプロパティを抽出
type OmitUser = Omit<User, "email">

ユースケース

  • ユーザー情報から個人情報を取り除いたデータを作成

3. Record<K, T> : ユニオン型から特定のキーと型を持つオブジェクトを作成**

type Role = "admin" | "user" | "guest"
type RolePermissions = Record<Role, boolean>

// ↑はこれと同じ
type RolePermissions = { 
	admin: boolean; 
	user: boolean; 
	guest: boolean; 
}

ユースケース

  • ユーザーの権限管理(admin, user, guestのみに限定したい)

4. Extract<T, U> : ユニオン型から指定した型にマッチするものだけを抽出

// Statusからactive, bannedだけを抽出
type Status = "active" | "inactive" | "banned"
type ActiveStatus = Extract<Status, "active" | "banned">

ユースケース

  • 特定の条件に合致する型だけを扱う

5. Exclude<T, U> : ユニオン型から指定した型を除外

// Statusからactive以外を抽出
type NonActiveStatus = Exclude<Status, "active">

ユースケース

  • 必要のない型を削除

4. 応用編:高度なMapped Typesとユーティリティ型の組み合わせ

1. プロパティの型を変換する

例えば、すべてのプロパティを string に変換する場合

type Stringify<T> = {
  [K in keyof T]: string
}

type StringifiedUser = Stringify<User>

ユースケース

  • 数値や日付データをすべて文字列として扱うケース

2. プロパティを一部変更する (Override<T, U> の応用)

特定のプロパティだけ変更したい場合

type Override<T, U> = {
  [K in keyof T]: K extends keyof U ? U[K] : T[K]
}

// `name` だけ型が `number` に
type UserWithNewName = Override<User, { name: number }>

ユースケース

  • 一部のプロパティの型を変更して新しい型を作る

5. 最後に

今回取り上げたTypeScriptのMapped Typesユーティリティ型を使うと、柔軟で再利用性の高い型定義 を作ることができ、開発体験が向上します。

基本のMapped TypesPartial<T>, Required<T>, Readonly<T>
便利なユーティリティ型Pick<T, K>, Omit<T, K>, Record<K, T>, Extract<T, U>, Exclude<T, U>
応用編:型の変換 (Stringify<T>)、一部変更 (Override<T, U>) など

これらを使いこなしてよいTypeScriptライフを!


参考サイト


採用拡大中!

アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニア仲間を募集しています!
少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう!

お問い合わせはこちらから↓
https://official.assisteng.co.jp/contact/

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?