keyof 用来返回一个class类型或者interface类型的所有key组成的联结类型。能够看上面的一个例子:
一: 当把keyof用在个别常见的class类型和interface类型上
type Point = { 0: number; height: number };interface Point2{name: string; age: number}type KeyOfPoint = keyof Point; // 0 | 'height'type KeyOfPoint2 = keyof Point2; // 'name' | 'age'const fn = (key: KeyOfPoint | KeyOfPoint2)=>{}fn(0) //no errorfn('height') //no errorfn('name') //no errorfn('age') //no errorfn('width') // error: 类型不匹配
在以上的代码外面 :
key: KeyOfPoint | KeyOfPoint2
就相当于:
key: 0 | 'height' | 'name' | 'age'
所以,当咱们调用:fn('width')
的时候就会报错,因为‘width’不在Point和Point2的key的列表外面。
二: 当把keyof用在index signature的class类型上时
number类型的index signature, 后果为: number
type Arrayish = { [n: number]: unknown };type A = keyof Arrayish; // type A = number
string类型的index signature,后果为: string | number
。这是因为,当我定义string类型的index signature时,我仍然能够给number类型的key,因为JavaScript会把对象的number类型的key强制转为string,比方obj[0]和obj['0']是相等的。
type Arrayish = { [n: string]: unknown };type A = keyof Arrayish; // type A = number | numberconst fn = (key: A)=>{}fn('xxx') // no errorfn(0) // no error
以上是keyof的通常应用场景,也是keyof被设计进去的初衷。然而,如果咱们把keyof用到enum, number,string等类型上会失去什么呢?
三: 当把keyof用在number类型的enum上
enum Colors { red, blue, yellow}type A = keyof Colors; // "toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"
当把keyof用在number类型的enum上时,会失去Number.prototype
上所定义的办法的名字(string格局)的联结类型。
四: 当把keyof用在string类型的enum上
enum Colors { red = 'red', blue = 'blue', yellow = 'yellow'}type A = keyof Colors; // number | "toString" | "charAt" | "charCodeAt" | "concat" | ...27 more... | "padEnd"
当把keyof用在string类型的enum上时,咱们就失去一个由number类型再加上String.prototype上定义的所有的办法的名字组成的一个联结类型。