1全プロパティを boolean にする
マップ型の最も素朴な形です。[K in keyof Product] で Product のキーを1つずつたどり、値の型をすべて boolean にしています。元の型とキーがぴったり同じ別の型ができるので、キーの過不足はエラーになります。
type Product = {
title: string;
price: number;
};
// Product と同じキーを持ち、値はすべて boolean の型を作る
type CheckedFlags = { [K in keyof Product]: boolean };
// { title: boolean; price: boolean } と同じ意味になる
const reviewFlags: CheckedFlags = { title: true, price: false };
console.log(reviewFlags.title);
console.log(reviewFlags.price);
// const bad: CheckedFlags = { title: true }; // price が足りないのでエラー
2T[K] で値の型を保ったまま readonly を付ける
値の型に T[K](インデックスアクセス型)を書くと「元の値の型をそのまま使う」という意味になります。キーの前に readonly を付ければ、全プロパティが書き換え不可になった複製の型が作れます。元の型は一切変更しない、というのがマップ型の使い方です。
// 全プロパティに readonly を付けた型を作る
type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type AppSettings = {
theme: string;
fontSize: number;
};
const lockedSettings: MyReadonly<AppSettings> = {
theme: "dark",
fontSize: 14,
};
console.log(lockedSettings.theme);
console.log(lockedSettings.fontSize);
// lockedSettings.theme = "light"; // readonly なので再代入はエラー
3? を付けて全プロパティを省略可能にする
キーの後ろに ? を付けると、全プロパティが省略可能な型になります。これは組み込みの Partial<T> の定義そのものです。「変更したい項目だけ渡す」更新関数が自然に書けるようになり、マップ型が日々の道具になる瞬間です。
// 全プロパティを省略可能にする(組み込みの Partial<T> と同じ定義)
type MyOptional<T> = { [K in keyof T]?: T[K] };
type Profile = {
nickname: string;
bio: string;
};
// 変更したい項目だけ受け取って上書きする
function updateProfile(current: Profile, changes: MyOptional<Profile>): Profile {
return { ...current, ...changes };
}
const base: Profile = { nickname: "Tar-kun", bio: "よろしく" };
console.log(updateProfile(base, { bio: "TypeScript勉強中" }));
4リテラル型のユニオンからキーを作る
in の右側は keyof でなくてもよく、リテラル型のユニオンを直接書けます。「候補の数だけキーを必ず持つ対応表」の型が作れて、キーが1つでも欠けるとエラーになります。候補のユニオンを型として既に持っているとき、その全候補ぶんの値を漏れなく用意させたい場面で使います。
type TimeSlot = "morning" | "afternoon" | "evening";
// ユニオンの候補1つずつがキーになる
type ReservationCount = { [K in TimeSlot]: number };
// 3つのキーをすべて書かないとエラーになる
const todayCounts: ReservationCount = {
morning: 2,
afternoon: 5,
evening: 3,
};
console.log(todayCounts.morning);
console.log(todayCounts.evening);
// const bad: ReservationCount = { morning: 1 }; // 残り2つが足りずエラー
5実務: フォームの型からエラー表示用の型を導出する
入力フォームの型から「項目ごとのエラーメッセージ(なければ null)」の型をマップ型で導出する実務例です。フォームに項目を追加すると FormErrors にも必須キーが自動で増え、エラー処理の書き忘れをコンパイラが教えてくれます。これがないと、フォームの型とエラーの型を手書きで二重管理し、項目の追加のたびに片方を直し忘れるバグが起きます。
type SignupForm = {
email: string;
password: string;
agreeToTerms: boolean;
};
// フォームと同じキーで「エラーメッセージか null」を持つ型を導出する
type FormErrors = { [K in keyof SignupForm]: string | null };
// SignupForm に項目を足すと、ここにも必須キーが増えて書き忘れを検出できる
const currentErrors: FormErrors = {
email: null,
password: "8文字以上にしてください",
agreeToTerms: null,
};
for (const message of Object.values(currentErrors)) {
console.log(message === null ? "OK" : "エラー: " + message);
}