问题背景
TypeScript从一开始就被开发用于对对象进行严格类型检查,并编写更具可预测性的JavaScript代码。为了确保在访问对象属性时的安全,出现了keyof运算符,它在TypeScript 2.1中引入。它允许创建表示在声明的对象类型中可用的字符串(和符号)键的集合的类型。
问题
在纯JavaScript中,对象的属性可以通过任何字符串进行查询,如果出错,结果将是undefined或错误,这只有在运行时才能发现。没有严格的类型检查,轻易会出现拼写错误或在重构时忘记更新键字符串。此外,通常需要构建一个仅接受特定对象或类型的正确键的函数。
解决方案
keyof运算符创建一个联合类型,包含类型的所有键。通过它,可以限制允许的键,提高API的安全性(例如,用于getter/setter函数),并创建通用的实用类型。
示例代码:
type User = { name: string; age: number; active: boolean }; type UserKey = keyof User; // "name" | "age" | "active" function getProp<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const user: User = { name: 'Tom', age: 33, active: true }; const age = getProp(user, 'age'); // age类型为number
关键特性:
keyof对数组返回什么,是否可以获取索引?
对于数组,keyof返回的是数组在JS中实际作为对象的键类型。通常这是索引字符串和数组的特殊属性。
示例代码:
type A = keyof number[]; // "length" | "toString" | "pop" | ... | number
keyof可以返回union-types的键吗?
是的,keyof对于union类型返回两个对象键的交集,而不是它们的并集。
示例代码:
type A = {a: string, b: number } type B = {b: number, c: boolean } type C = keyof (A | B); // "b"
如果对象属性是可选的,会发生什么?keyof支持“?”吗?
是的,可选属性也包含在结果键类型中,但这并不意味着该属性在运行时必定存在于对象中。
示例代码:
type D = { a: string; b?: number }; type DK = keyof D; // "a" | "b"
编写函数getProperty(obj, key),使用字符串类型的键调用,不存在的键导致的错误——错误仅在运行时出现。
优点:
缺点:
使用泛型:getProperty<T, K extends keyof T>(),密钥类型严格限制在结构的键。
优点:
缺点: