TypeScript keyof 怎么用
很多前端朋友刚用 TypeScript 时,常觉得它比 JavaScript 多了些“条条框框”,但这些框框其实能帮我们少踩很多运行时的坑——比如想提取一个对象里所有属性的名字时,不用再手动写死字符串,keyof 就能派上用场。
先搞懂:`keyof` 到底是啥?
简单说,keyof 就是“把一个对象的所有属性名,变成一个固定的类型集合”。举个生活化的例子:你有个“奶茶订单”对象,里面有三个属性:size: "中杯"、sugar: "少糖"、temperature: "热饮",那这个订单的所有属性名就是"size"、"sugar"、"temperature",keyof 就会把这几个名字变成一个专属的类型,只能用这三个名字当值,别的都不行。

基础用法:直接提取对象的属性类型
先写个基础的对象类型,再用 keyof 拿它的属性名类型:
`typescript
// 定义一个用户信息的类型,对应对象的结构
type User = {
name: string;
age: number;
email: string;
};
// 用 keyof 提取 User 所有属性名的类型
type UserKey = keyof User;
`
这时候 UserKey 就相当于"name" | "age" | "email"——是一个只能取这三个值的联合类型。比如你写个函数,要专门用来拿用户某个属性的值,就可以用它来限制参数:
`typescript
function getUserInfo(user: User, key: UserKey) {
return user[key]; // 只会允许你传 name、age、email
}
// 正确用法:传的是合法的属性名
getUserInfo({ name: "小周", age: 25, email: "zhou@xxx.com" }, "name");
// 错误用法:传"phone",不在 User 的属性里,TypeScript 会直接标红报错
getUserInfo(user, "phone");
`
是不是很实用?再也不用担心写错属性名,运行时才发现phone不存在的问题了。
进阶用法:对泛型对象的属性做限制
如果遇到“不知道对象具体结构,但要限制只能用它的属性”的场景,keyof 搭配泛型会更灵活。比如要写一个“更新用户信息”的函数,只能改现有的属性,不能加新属性:
`typescript
// 泛型 T 是传入的对象类型,K 必须是 T 的属性名(用 keyof T 约束)
function updateUser<T, K extends keyof T>(user: T, key: K, value: T[K]) {
user[key] = value;
}
// 用 User 类型测试
const myUser: User = { name: "小周", age: 25, email: "zhou@xxx.com" };
// 正确:改 name 属性,值是 string 类型
updateUser(myUser, "name", "小张");
// 正确:改 age 属性,值是 number 类型
updateUser(myUser, "age", 26);
// 错误:改不存在的"gender"属性,TypeScript 会报错
updateUser(myUser, "gender", "男");
// 错误:给 age 传 string 类型的值,和 User 里 age 的 number 类型不匹配
updateUser(myUser, "age", "二十六");
`
这里的K extends keyof T就是说,K只能是T的属性,既保证了属性存在,还让值的类型和原属性匹配,相当于同时做了“属性合法性”和“值类型检查”。
注意:`keyof` 不止能用在普通对象上
除了普通对象,keyof 还能用于数组、类甚至枚举的属性名:
比如数组的话,keyof (string[])会得到"length" | "push" | ...这些数组的内置方法和属性;如果是类,keyof 会提取类的公有属性和方法的名字。不过用得最多的还是普通对象,记住“keyof是提取对象属性名的类型集合”这个核心就够了。
总结一下,keyof 就是 TypeScript 给我们的“属性名合法性检查工具”,从简单的属性读取函数,到灵活的泛型函数,它都能帮我们提前挡住写错名字、传错值的坑,让代码更安全,写起来也更省心。