TL;DR

キーの集合(多くは keyof で作る)を走査して、新しい型を作る TypeScript のジェネリックな型。ある型をもとに別の型を定義できるので、同じ記述を繰り返さずに済む。

なぜ必要か

TypeScript Handbook によると、型を繰り返し書かずに、別の型をもとに新しい型を作りたいときに使う。Effective TypeScript でも、DRY は型にも当てはまるとして、keyof やマップ型を使って型の重複を減らすことを勧めている。

仕組み

マップ型は、インデックスシグネチャの構文をもとにしており、[Property in keyof Type] でキーを 1 つずつ取り出して値の型を決める。readonly と ? の修飾子を、+ で付けたり - で外したりできる。TypeScript 4.1 からは as でキーを付け替えられ、テンプレートリテラル型で新しいキー名を作ったり、条件型で never にしてキーを除いたりできる。

例

TypeScript Handbook の例では、OptionsFlags が型のすべてのプロパティの値を boolean に変える。

type OptionsFlags<Type> = {
  [Property in keyof Type]: boolean
}
 
type Features = {
  darkMode: () => void
  newUserProfile: () => void
}
 
type FeatureOptions = OptionsFlags<Features>
// { darkMode: boolean; newUserProfile: boolean; }

組み込みの Record、Partial<T>、Pick<T, Keys> もマップ型である。

注意点

Effective TypeScript によると、マップ型は type では使えるが、interface では表現できない。

関連

出典