開発効率アップ!TypeScriptの「extends keyof」と「in keyof」で型操作をマスター
TypeScriptにおける「extends keyof」と「in keyof」の意味
extends keyof
と in keyof
は、keyof
と組み合わせて、より複雑な型の操作を行うための構文です。それぞれ、以下のような意味を持ちます。
extends keyof
extends keyof
は、ある型が別の型のプロパティ名のいずれかを拡張する必要があることを表します。
例えば、以下のコードでは、Person
型は Name
または Age
というプロパティを持つ必要があります。
interface Person {
name: string;
age: number;
}
type T extends keyof Person;
// T は "name" | "age" のいずれかになる
extends keyof
は、以下のようなユースケースで役立ちます。
- ジェネリック型を使って、特定のプロパティを持つオブジェクトを操作する関数を作成する場合
- オブジェクトの特定のプロパティの値にのみアクセスできる型を定義する場合
in keyof
in keyof
は、ある型が別の型のプロパティ名を持つかどうかをチェックするために使用されます。
例えば、以下のコードでは、obj
オブジェクトが name
というプロパティを持っているかどうかをチェックしています。
const obj = {
age: 30,
};
if ("name" in keyof obj) {
// obj は "name" というプロパティを持っている
} else {
// obj は "name" というプロパティを持っていない
}
- オブジェクトに特定のプロパティが存在するかどうかをチェックする場合
- オブジェクトのプロパティ名に基づいて、条件分岐を行う場合
extends keyof
1 ジェネリック型を使って、特定のプロパティを持つオブジェクトを操作する関数
function getProperty<T extends keyof Object>(obj: Object, prop: T): Object[T] {
return obj[prop];
}
const person = {
name: "John Doe",
age: 30,
};
const name = getProperty(person, "name"); // "John Doe"
const age = getProperty(person, "age"); // 30
2 オブジェクトの特定のプロパティの値にのみアクセスできる型を定義する
interface Person {
name: string;
age: number;
}
type Name = keyof Person;
const person: Record<Name, string> = {
name: "John Doe",
// age: 30 // エラー: "age" は "Name" 型ではない
};
このコードでは、Person
型のオブジェクトの name
プロパティの値にのみアクセスできる Name
型を定義しています。
in keyof
1 オブジェクトに特定のプロパティが存在するかどうかをチェックする
const obj = {
age: 30,
};
if ("name" in keyof obj) {
// obj は "name" というプロパティを持っている
} else {
// obj は "name" というプロパティを持っていない
}
2 オブジェクトのプロパティ名に基づいて、条件分岐を行う
const obj = {
name: "John Doe",
age: 30,
};
const prop = "name";
switch (prop) {
case "name":
console.log("The name is " + obj.name);
break;
case "age":
console.log("The age is " + obj.age);
break;
default:
console.log("Unknown property");
}
このコードでは、obj
オブジェクトのプロパティ名 prop
に基づいて、条件分岐を行っています。
これらのサンプルコードは、extends keyof
と in keyof
の使い方を理解するのに役立ちます。
extends keyof と in keyof の他の方法
1 ジェネリック型を使って、特定のプロパティを持つオブジェクトを操作する関数
extends keyof
を使わずに、以下のコードのように keyof
と typeof
を組み合わせて同じ機能を実現できます。
function getProperty<T>(obj: object, prop: keyof typeof obj): typeof obj[prop] {
return obj[prop];
}
const person = {
name: "John Doe",
age: 30,
};
const name = getProperty(person, "name"); // "John Doe"
const age = getProperty(person, "age"); // 30
2 オブジェクトの特定のプロパティの値にのみアクセスできる型を定義する
interface Person {
name: string;
age: number;
}
type Name = keyof Person;
const person: Record<Name, string> = {
name: "John Doe",
// age: 30 // エラー: "age" は "Name" 型ではない
};
1 オブジェクトに特定のプロパティが存在するかどうかをチェックする
const obj = {
age: 30,
};
if (obj.hasOwnProperty("name")) {
// obj は "name" というプロパティを持っている
} else {
// obj は "name" というプロパティを持っていない
}
2 オブジェクトのプロパティ名に基づいて、条件分岐を行う
const obj = {
name: "John Doe",
age: 30,
};
const prop = "name";
const keys = Object.keys(obj);
for (const key of keys) {
if (key === prop) {
console.log("The " + prop + " is " + obj[prop]);
break;
}
}
extends keyof
と in keyof
は、いくつかの代替方法で表現できます。どの方法を使うかは、状況によって異なります。
typescript keyof