在 TypeScript 中,keyof
关键字是一个有用的类型操作符,它用于获取一个类型所有公共属性键的联合(Union)。当你想要操作一个类型的键而不是它的值时,keyof
操作符非常有用。
基本用法
对于任何类型 T
,keyof T
会产生一个类型,该类型是 T
的所有公共属性键的联合。
interface Person {
name: string;
age: number;
}
type PersonKeys = keyof Person; // "name" | "age"
在这个例子中,PersonKeys
是一个类型,它包含了 Person
接口中所有键的联合,即 "name"
和 "age"
。
与索引签名一起使用
keyof
操作符经常与索引签名(Indexable Type)一起使用,索引签名允许你通过键来访问对象的属性。
interface Person {
[name: string]: string | number;
age: number;
}
type PersonKeys = keyof Person; // string | "age"
在这个例子中,Person
接口有一个字符串索引签名,这意味着它可以有任意数量的字符串键。keyof Person
将包含所有这些可能的键以及明确声明的属性键 "age"
。
类型守卫和断言
keyof
可以用来创建类型守卫,确保某个键存在于对象中。
interface Person {
name: string;
age: number;
}
function getPersonProperty<T extends keyof Person>(key: T) {
const person: Person = { name: "Alice", age: 30 };
return person[key]; // 使用 key 作为索引访问 person 对象
}
const name: string = getPersonProperty("name"); // OK
const age: number = getPersonProperty("age"); // OK
过滤键
keyof
可以与 in
操作符结合使用,来过滤出符合特定条件的键。
interface Person {
name: string;
age: number;
gender?: string;
}
type RequiredPersonKeys = keyof Person & ('name' | 'age'); // "name" | "age"
function printRequiredInfo(person: Person) {
if ('name' in person) {
console.log(person.name);
}
if ('age' in person) {
console.log(person.age);
}
}
在这个例子中,RequiredPersonKeys
是一个类型,它只包含 Person
接口中那些被声明为必需的键。
与泛型结合
keyof
可以与泛型结合使用,以提供更通用的类型。
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const person = { name: "Alice", age: 30 };
const name = getProperty(person, 'name'); // string
const age = getProperty(person, 'age'); // number
在这个例子中,getProperty
函数接受一个对象和一个键,然后返回该键对应的值。泛型 K
被约束为 T
的键之一,这样 TypeScript 就可以确保键是有效的。
keyof
是 TypeScript 提供的一个强大的工具,它允许你以类型安全的方式操作对象的键。通过使用 keyof
,你可以编写出更灵活和可重用的代码。