公開日: 2023/05/13 @Miz_dev
オブジェクトのプロパティを動的に追加したい時に使用する。
「key」の部分は key では無い文言でも問題ないが、慣習的に「key」がよく使用される。
export type User = {
name: string;
[key: string]: string;
};
const user: User = {
name: "テスト",
account: "test",
};
Index Signature で string 型を指定しているので、number 型が入るとエラーとなる。
export type User = {
name: string;
age: number;
[key: string]: string;
};
const user: User = {
name: "テスト",
age: 25,
account: "test",
};
以下のように Union Types で指定することで回避することが可能。
export type User = {
name: string;
age: number;
[key: string]: string | number;
};
const user: User = {
name: "テスト",
age: 25,
account: "test",
};
ただし、他のプロパティと型が違う場合には色々な型を付与しなければならないのは、Index Signature の欠点。
以下のように、undefined を付与することで対処は出来る。
export type User = {
name: string;
age: number;
[key: string]: string | number | undefined;
};
const user: User = {
name: "テスト",
age: 25,
account: "test",
};
ただし、存在するプロパティに対しても undefined が付与されてしまうため、使い勝手が悪くなってしまう。
そのため、typeof 等を使用して絞り込まないとメソッドにもアクセス出来ない。
Index Signature は便利ではあるが、型がもろくなってしまうので多用するべきではない。
以下の 2 点に大きく分類できる。
export type User = {
name: string;
} & PersonalData;
type PersonalData = {
// height: number;
// weight: number;
[K in "height" | "weight"]: number;
};
const user: User = {
name: "テスト",
height: 178,
weight: 65,
};
以下のように keyof や更に keyof tepeof で変数から直接プロパティ名を指定することも出来る。
export type User = {
name: string;
} & PersonalData;
const foo = {
height: 200,
weight: 100,
};
type PersonalData = {
// height: number;
// weight: number;
[K in keyof typeof foo]: number;
};
const user: User = {
name: "テスト",
height: 178,
weight: 65,
};
以下のように Mapped Types の後に「?」を付けることでオプショナルにすることが出来るため、**「**weight」が無くても必須ではないのでエラーとならなくなる。
export type User = {
name: string;
} & PersonalData;
type PersonalData = {
// height: number;
// weight: number;
[K in "height" | "weight"]?: number;
};
const user: User = {
name: "テスト",
height: 178,
};
ちなみに、このオプショナルの書き方は Index Signature では出来ないため注意。
以下のようにオブジェクトのような感じで PersonalData[K]とすることで、PersonalData の number 等を取り出すことができる。
type PersonalData = {
height: number;
weight: number;
realName: string;
};
type optionalPersonalData = {
[K in keyof PersonalData]?: PersonalData[K];
// height: number;
// weight: number;
};
また、以下のように「-?」とすることで、反対にプロパティを必須にすることが出来る。
type PersonalData = {
height?: number;
weight?: number;
realName?: string;
};
type RiquiredPersonalData = {
[K in keyof PersonalData]-?: PersonalData[K];
// height: number;
// weight: number;
};