導入
Partial や Readonly のようなユーティリティ型は便利ですが、「全プロパティを boolean にする」のような、自分だけの独自の変形をしたいこともあります。そんなときは mapped types([K in keyof T])を使って、自分でユーティリティ型を作れます。
説明
{ [K in keyof T]: 型 } は「T の各プロパティ名を1つずつ取り出して、新しい型に当てはめる」という書き方です。
interface User {
id: number;
name: string;
}
type Flags<T> = {
[K in keyof T]: boolean;
};
const userFlags: Flags<User> = { id: true, name: false };
console.log(userFlags);
これは、実は組み込みの Readonly<T> を自作しているのと同じしくみです。
type MyReadonly<T> = {
readonly [K in keyof T]: T[K];
};
interface Point {
x: number;
y: number;
}
const p: MyReadonly<Point> = { x: 1, y: 2 };
console.log(p.x, p.y);
// p.x = 10; // エラー: readonly なので書き換え不可
T[K] は前のレッスンで学んだインデックスアクセス型です。「元のプロパティの型そのまま」を使うときに組み合わせます。
やってみよう
Flags<User> の name を true に変えて、console.log(userFlags) で結果を確かめましょう。
演習
interface Book { title: string; price: number; } から、[K in keyof T]: string で全プロパティを string 型に変換する Stringify<T> という mapped type を作ってください。Stringify<Book> 型の変数 b に title: "本", price: "1000円" を入れ、console.log(b.price) で表示してください。
ヒント1を見る
type Stringify<T> = { [K in keyof T]: string }; と書きます。
ヒント2を見る
const b: Stringify<Book> = { title: "本", price: "1000円" }; console.log(b.price);