TypeScriptのUnion型とMapped Typesの活用法!初心者向け解説
生徒
「TypeScriptを使っているのですが、Union型を便利に扱う方法ってありますか?」
先生
「Mapped Typesという機能を使うと、Union型をベースにして型を自動生成できるので、とても便利ですよ。」
生徒
「難しそうですが、具体的にどういう仕組みなんですか?」
先生
「プログラミングの基本から、ひとつずつ分かりやすく解説していきますね。」
1. Union型とは何か?基本をおさらい
まずは基礎固めです。Union型(ユニオンがた)とは、TypeScriptで変数やプロパティが「複数の型のうち、どれか一つである」ことを許容する仕組みです。例えば、ユーザーの権限が「管理者」「編集者」「閲覧者」のいずれかである場合、それらをひとまとめにして定義できます。
プログラミング未経験の方に例えるなら、飲み物を注文する際に「コーヒー、紅茶、緑茶のどれかを選んでください」というメニュー表のようなものです。これを使うと、プログラムが想定外の値を扱わないようになり、エラーを防げます。
type Role = "admin" | "editor" | "viewer";
let userRole: Role = "admin";
2. Mapped Typesとは?魔法の仕組み
Mapped Types(マップドタイプ)は、既存の型から新しい型を変換して作る機能です。例えば、あるオブジェクトの全プロパティを「読み取り専用(変更不可)」にしたいとき、一つずつ手書きするのは大変ですよね。Mapped Typesを使えば、それを一瞬で自動化できます。
これは、名簿の全員に対して一斉に名前の横に「さん」をつける作業を、魔法で自動実行するようなイメージです。プログラムを効率的に書くための、非常に強力な武器となります。
3. Union型とMapped Typesの組み合わせ
Union型とMapped Typesを組み合わせると、さらに表現の幅が広がります。例えば、特定の役割(Role)ごとに、設定項目を持たせたいとします。これを自動生成することで、コードの重複を減らし、管理が楽になります。
具体的には、Union型の各要素を「キー」として使い、それに対応する値を定義します。これにより、役割が増えたときも、Union型を書き換えるだけで他の関連する型も自動で追従するようになります。
type Role = "admin" | "editor" | "viewer";
// Roleの各要素をキーにして、真偽値(true/false)を持たせる型を作る
type RolePermissions = {
[K in Role]: boolean;
};
const permissions: RolePermissions = {
admin: true,
editor: true,
viewer: false
};
4. なぜこの組み合わせが現場で使われるのか
システム開発の現場では、同じような定義を何度も繰り返すのが最も危険です。もし定義を書き換える場所が複数あると、片方の修正を忘れてバグが発生する原因になります。これを「保守性が悪い」と言います。
Mapped Typesを使って自動化しておけば、修正場所は「情報の元となる場所だけ」で済みます。これは、プログラミングにおいて非常に重要な「DRY原則(Don't Repeat Yourself=同じことを繰り返さない)」を守るための極めて賢い手法なのです。
5. ユーティリティ型を活用した応用テクニック
TypeScriptには、よく使われる型変換を簡単に行える「ユーティリティ型」という便利な道具箱が最初から用意されています。これとMapped Typesを組み合わせることで、より高度な操作が可能になります。
例えば、全てのプロパティを「必須ではない(あってもなくても良い)」状態にするPartial型などは非常に有名です。これらを自作のMapped Typesと組み合わせれば、どんな複雑なデータ構造も型定義できるようになります。
type UserInfo = {
name: string;
age: number;
};
// 全てを必須ではなくす(省略可能にする)
type PartialUserInfo = Partial<UserInfo>;
const user: PartialUserInfo = {
name: "山田"
// ageがなくてもエラーにならない
};
6. 実務で遭遇する型エラーと対処法
TypeScriptを書いていると、真っ赤なエラー線に悩まされることがあります。Mapped Typesを使う際にありがちなのは、本来存在しないキーを操作しようとしてしまうことです。しかし、TypeScriptの型システムは、それをコンパイル(プログラムを動かす前)の段階でしっかり指摘してくれます。
エラーが出たときは怖がらずに、どの型がどのキーを求めているのか、TypeScriptからのメッセージをよく読んでみましょう。Mapped Typesをうまく使うことで、この型チェックを強力に味方にできるため、安心して開発を進められるようになります。
type Config = {
readonly [K in "api" | "db"]: string;
};
const myConfig: Config = {
api: "https://api.example.com",
db: "localhost"
};
// myConfig.api = "new-url"; // これはエラーになる(readonlyのため)