TypeScript系列:第四篇 - typeof 与 keyof
在 TypeScript系列:第三篇 - 泛型 有提及 keyof 的使用。
本文将详细介绍 keyof
和 typeof
运算符的基本概念、应用场景以及如何结合使用它们来提高代码的类型安全性。
keyof
keyof
运算符用于获取一个类型的所有键名(属性名)。
例如,对于一个接口或类型,keyof
可以提取出所有属性的名字。
interface Person {
name: string;
age: number;
}
type PersonKeys = keyof Person; // "name" | "age"
应用场景
类型安全
确保访问的属性在对象上是有效的,避免运行时错误
interface Person {
name: string;
age: number;
}
function getPersonProp(person: Person, prop: keyof Person) {
return person[prop];
}
const p: Person = { name: 'ligang', age: 34 };
getPersonProp(p, 'name');
getPersonProp(p, 'address'); // 类型“"address"”的参数不能赋给类型“keyof Person”的参数
映射类型
在已有类型的基础上创建新类型。
将 Custom
所有类型改为 boolean
,并形成新的 myCustom
类型。
type OptionsFlags<T> = {
[Property in keyof T]: boolean;
};
interface Custom {
a: () => void;
b: () => void;
}
type myCustom = OptionsFlags<Custom>; // { a: boolean; b: boolean;}
条件映射类型
在上述映射类型的基础基础上,可以根据属性类型进行动态类型转换。
将 Custom
所有 string
类型改为 boolean
(其他类型保留),并形成新的 myCustom
类型。
type OptionsFlags<T> = {
[Property in keyof T]: T[Property] extends String ? boolean : T[Property];
};
interface Custom {
a: () => void;
b: string;
c: number;
}
type myCustom = OptionsFlags<Custom>; // { a: () => void; b: boolean; c: number}
keyof
具有特别强的灵活性。其可以针对获取的键名,做个性化改造!
将 Custom
所有类型改为可选,并形成新的 myCustom
类型。
type Partial<T> = {
[P in keyof T]?: T[P];
};
interface Custom {
foo: number;
}
type myCustom = Partial<Custom>; // { foo?: number }
typeof
typeof
运算符用于获取一个变量的类型。
这在 TypeScript 中非常有用,可以动态地从变量中提取类型信息。
const person = {
name: 'ligang',
age: 34
};
type PersonType = typeof person; // { name: string; age: number; }
应用场景
类型推导
从变量中推导出类型,用于类型声明。
let h = 'hello';
let w: typeof h = 'world'; // let w: string
类型安全
在函数中使用 typeof
来限制参数类型。
const person = { name: 'ligang', age: 34 };
function greet(name: typeof person.name) { // name: string
console.log(`Hello, ${name}!`);
}
类型守卫
此类型守卫函数中,isNumber
检查 x
是否为 number
类型。
function isNumber(x: number | string): x is number {
return typeof x === "number";
}
结合使用
获取一个对象所有键的联合类型
在实际开发中,经常需要结合使用 keyof
和 typeof
来实现更复杂的类型操作。
const person = { name: 'ligang', age: '34' };
type Person = keyof typeof person; // "name" | "age"
1️⃣ typeof person
typeof person // { name: string; age: string; }
从变量 person
中提取类型信息;返回的是 person
的类型,而不是 person
本身。
2️⃣ keyof
keyof { name: string; age: string; } // "name" | "age"
⚠️ 注意:keyof person
会导致编译错误。这里 person 是具体的对象,不是类型。
获取一个枚举所有键的联合类型
enum Color {
Red,
Green,
Blue,
}
type ColorKeys = keyof typeof Color; // "Red" | "Green" | "Blue"
const color: ColorKeys = 'Red';
typeof Color
会获取到 Color
枚举的类型,它包含了枚举的所有成员。
使用 keyof
操作符,可以得到一个由这些成员名组成的联合类型。
🌴🌴🌴 typeof
针对的是变量;keyof
面向的是类型。