言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

TypeScript辞典

  1. トップページ
  2. TypeScript辞典
  3. マップ型 { [K in keyof T]: ... }

マップ型 { [K in keyof T]: ... }

対応: TypeScript 2.1(2016)

既存の型のプロパティを変換して新しい型を生成する機能です。繰り返しの多い型定義を自動化でき、『Partial』『Readonly』などの組み込みユーティリティ型の内部実装にも使われています。

構文

// マップ型の基本構文
type 型名 = {
	[K in keyof T]: 新しい型;
};

// 修飾子の追加・削除
type 型名 = {
	+readonly [K in keyof T]+?: 新しい型; // readonly と ? を追加します。
	-readonly [K in keyof T]-?: 新しい型; // readonly と ? を削除します。
};

構文一覧

構文概要
[K in keyof T]型TのすべてのプロパティキーをKとして列挙します。マップ型の基本パターンです。
keyof T型Tのすべてのプロパティキーをユニオン型として取得します。
[K in Union]特定のユニオン型のメンバーをキーとして列挙します。
+?: / -?:修飾子(プロパティに付与される readonly やオプショナル記号『?』のこと)のオプショナルを追加(+)または削除(-)します。
+readonly / -readonlyreadonlyを追加(+)または削除(-)します。
as 節(キーの変換)[K in keyof T as NewKey]の形式でキー名を変換できます(TypeScript 4.1以降)。

サンプルコード

// 基本的なマップ型: 既存の型のすべてのプロパティを変換します。
type User = {
	id: number;
	name: string;
	email: string;
};

// すべてのプロパティをstring型に変換します。
type UserAsStrings = {
	[K in keyof User]: string;
};
// { id: string; name: string; email: string; } になります。

// Partial<T>の手動実装: すべてのプロパティをオプショナルにします。
type MyPartial<T> = {
	[K in keyof T]?: T[K]; // T[K]は元のプロパティの型を保持します。
};
type PartialUser = MyPartial<User>;
const partial: PartialUser = { name: "member_1" }; // idとemailを省略できます。
console.log(partial.name); // 『member_1』と出力されます。

// Readonly<T>の手動実装: すべてのプロパティをreadonly化します。
type MyReadonly<T> = {
	readonly [K in keyof T]: T[K];
};
const readonlyUser: MyReadonly<User> = { id: 1, name: "member_2", email: "member_2@wp-p.info" };
// readonlyUser.name = "member_1"; // エラー: readonlyのため変更できません。

// -?:で全プロパティのオプショナルを削除します(Required<T>の実装)。
type MyRequired<T> = {
	[K in keyof T]-?: T[K];
};

// ユニオン型をキーとして使用します。
type Flags = "dark" | "sidebar" | "notifications";
type FlagMap = {
	[K in Flags]: boolean;
};
// { dark: boolean; sidebar: boolean; notifications: boolean; } になります。
const settings: FlagMap = { dark: true, sidebar: false, notifications: true };
console.log(settings.dark); // trueと出力されます。

// as節でキー名を変換します(TypeScript 4.1以降)。
type Getters<T> = {
	[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
// { getId: () => number; getName: () => string; getEmail: () => string; } になります。

実行すると次のように出力されます。

npx ts-node ts_mapped_type.ts
member_1
true

概要

マップ型は`{ [K in keyof T]: ... }`という構文で、既存の型のプロパティをすべて変換した新しい型を生成します。`Partial`・`Readonly`・`Required`・`Pick`といったTypeScriptの組み込みユーティリティ型は、すべてマップ型を使って実装されています。

修飾子(`+?:` / `-?:` / `+readonly` / `-readonly`)を使うことで、プロパティのオプショナル状態やreadonlyを変換後の型に追加・削除できます。`-?:`を使うと`Required`のように「全プロパティを必須化」する型を作れます。

TypeScript 4.1以降では`as`節を使ってキー名も変換できます。テンプレートリテラル型と組み合わせると、`getId()`・`getName()`のようなゲッター型を自動生成することもできます。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。