TypeScriptの`for...in`ループと`Object.keys()`でカスタムリテラル型を反復処理する方法
TypeScript でカスタムリテラル型を反復処理する方法
Object.keys() と for...in ループを使用する
この方法は、カスタムリテラル型のすべてのプロパティキーを反復処理するのに役立ちます。
type User = {
name: string;
age: number;
email: string;
};
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const key in user) {
console.log(key, user[key]); // name 太郎, age 30, email [email protected]
}
利点
- シンプルで分かりやすい
欠点
- プロパティの順序が保証されない
- プロパティの値にのみアクセスできません
type User = {
name: string;
age: number;
email: string;
};
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const value of Object.values(user)) {
console.log(value); // 太郎, 30, [email protected]
}
ジェネリック型とイテレータを使用する
この方法は、カスタムリテラル型のプロパティキーと値の両方にアクセスできる、より柔軟な方法を提供します。
type User = {
name: string;
age: number;
email: string;
};
function iterateUser<T extends User>(user: T): IterableIterator<[keyof T, T[keyof T]]> {
return function* () {
for (const key in user) {
yield [key, user[key]];
}
};
}
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const [key, value] of iterateUser(user)) {
console.log(key, value); // name 太郎, age 30, email [email protected]
}
- プロパティの順序を制御できる
- プロパティキーと値の両方にアクセスできる
- コードが少し複雑になる
どの方法を選択するべきか?
最適な方法は、特定の状況によって異なります。
- プロパティキーと値の両方にアクセスする必要があるか、またはプロパティの順序を制御する必要がある場合は、ジェネリック型とイテレータを使用する必要があります。
- プロパティの値にのみアクセスする必要がある場合は、
Object.values()
とfor...of
ループを使用するとよいでしょう。 - 単にプロパティキーを反復処理する必要がある場合は、
Object.keys()
とfor...in
ループを使用するのが最も簡単です。
type User = {
name: string;
age: number;
email: string;
};
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const key in user) {
console.log(key, user[key]); // name 太郎, age 30, email [email protected]
}
type User = {
name: string;
age: number;
email: string;
};
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const value of Object.values(user)) {
console.log(value); // 太郎, 30, [email protected]
}
type User = {
name: string;
age: number;
email: string;
};
function iterateUser<T extends User>(user: T): IterableIterator<[keyof T, T[keyof T]]> {
return function* () {
for (const key in user) {
yield [key, user[key]];
}
};
}
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const [key, value] of iterateUser(user)) {
console.log(key, value); // name 太郎, age 30, email [email protected]
}
in
演算子を使用して、オブジェクトのプロパティが存在するかどうかを確認できます。この演算子を使用して、カスタムリテラル型のすべてのプロパティキーを反復処理することもできます。
type User = {
name: string;
age: number;
email: string;
};
const user: User = {
name: "太郎",
age: 30,
email: "[email protected]",
};
for (const key in user) {
if (user.hasOwnProperty(key)) {
console.log(key, user[key]); // name 太郎, age 30, email [email protected]
}
}
hasOwnProperty()
メソッドを使用するよりも簡潔なコードになる場合がある
シンボルを使用する
シンボルを使用して、カスタムリテラル型のプロパティを独自に識別できます。シンボルを使用して、プロパティキーを反復処理し、プロパティ値にアクセスすることもできます。
type User = {
[key: symbol]: any;
};
const nameSymbol = Symbol("name");
const ageSymbol = Symbol("age");
const emailSymbol = Symbol("email");
const user: User = {
[nameSymbol]: "太郎",
[ageSymbol]: 30,
[emailSymbol]: "[email protected]",
};
for (const key in user) {
if (typeof key === "symbol") {
console.log(key, user[key]); // Symbol(name) 太郎, Symbol(age) 30, Symbol(email) [email protected]
}
}
- プロパティキーを独自に識別できる
- シンボルは、比較やキーとして使用する場合に注意が必要
デコレータを使用する
デコレータを使用して、カスタムロジックをクラスやプロパティに挿入できます。デコレータを使用して、カスタムリテラル型のプロパティを反復処理するロジックを追加することもできます。
type User = {
name: string;
age: number;
email: string;
};
function enumerable(target: any, propertyKey: string | symbol) {
const originalDescriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
if (originalDescriptor) {
Object.defineProperty(target, propertyKey, {
...originalDescriptor,
enumerable: true,
});
}
}
class User {
@enumerable
name: string;
@enumerable
age: number;
@enumerable
email: string;
}
const user = new User();
user.name = "太郎";
user.age = 30;
user.email = "[email protected]";
for (const key in user) {
console.log(key, user[key]); // name 太郎, age 30, email [email protected]
}
- カスタムロジックを非侵襲的に挿入できる
- デコレータは、すべての TypeScript コンパイラでサポートされているわけではない
typescript types