Appearance
keyof
keyof 操作符用来提取接口、对象、类的属性的名称。
keyof 操作接口类型
返回值为一个联合类型("key1" | "key2" | ...
)
js
interface Animal {
name : string;
age : number;
}
type AnimalKey = keyof Animal; // "name" | "age"
keyof 操作对象
返回值为一个联合类型("key1" | "key2" | ...
)
js
const animal = {
name : "瓜子",
age: 1
}
const a = Object.create(animal)
// 错误的
type AnimalKey1 = keyof animal; // Cannot find name 'animal'
// 正确的
type AnimalKey1 = keyof typeof animal; // "name" | "age"
// 正确的
type AnimalKey1 = keyof typeof a; // "string" | "number" | "symbol"
keyof 操作 类
返回值为一个联合类型("key1" | "key2" | ...
)
js
class Animal {
name: string;
// 保护类型
protected age: number;
// 私有类型属性
private sex: number;
// 静态方法
static getInstance() {
return Animal
}
constructor(name: string, age: number, sex: number) {
this.name = name
this.age = age
this.sex = sex
}
getName() {
return this.name
}
}
// 正确的
type AnimalKey2 = keyof Animal; // "name" | "getName"
为什么获取不到 Class 类中私有属性、保护类型、静态类型?
下面我们看转换后的结果
js
var Animal = /** @class */ (function () {
function Animal(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
}
// 静态方法
Animal.getInstance = function () {
return Animal
}
Animal.prototype.getName = function () {
return this.name
}
return Animal
})()
可以看出转换后其保护类型属性、私有类型属性不会显式的存在于对象的属性或者原型中,所以keyof
获取不到对应的属性
js
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
// 正确的
type AnimalKey2 = keyof Animal; // "bark" | "name" | "getName"
作用
- 操作键名的时候进行限制
ts
const prop = <T, K extends keyof T>(obj: T, key: K): any => {
return obj[key]
}
const obj = {
name: "战三",
}
prop(obj, "na") // Argument of type '"na"' is not assignable to parameter of type '"name"'.
in keyof
和extends keyof
的区别
首先我们需要分别了解in keyof
和 extends keyof
的作用。
extends keyof
生成一个继承于对象 Key 类型的子集 (联合类型),就像上面的 K extends keyof person
其结果为"name"、 "age"、"address" 三个类型随意组合,即可以是 "name" | "age"
、 "name" | "address" ...
js
const person = {
"name": "张三",
"age": 12,
"address": "南京"
}
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type MiniPerson = Exclude<keyof typeof person, "address"> // "name" | "age"
type LargePerson = Exclude<keyof typeof person, "address"> | "sex" // "name" | "age" | "sex"
// 在这里K是联合类型,传入的key可以是K中的一种
// K === "name"|"age"
const prop = <T, K extends keyof T>(obj: T, key: K): any => {
return obj[key]
}
const key1= "name"
prop(person, key1 as MiniPerson)
prop(person , key1 as LargePerson)
in keyof
其返回的是一个 对象 Key 类型 中某一个 Key 的字符串(字符串类型),所以其常用于对象中定义 Key
ts
const person = {
"name": "张三",
"age": 12,
"address": "南京"
}
type Person = typeof person
const b = {
[K in keyof Person] : Person[K] // K得是一个字符串,而不能是一个联合类型
}
js
const person = {
"name": "张三",
"age": 12,
"address": "南京"
}
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type MiniPerson = Exclude<keyof typeof person, "address"> // "name" | "age"
type LargePerson = Exclude<keyof typeof person, "address"> | "sex" // "name" | "age" | "sex"
// 在这里K是联合类型,传入的key可以是K中的一种
// K === "name"|"age"
const prop = <T, K extends keyof T>(obj: T, key: K): any => {
return obj[key]
}
// const prop1 = <T, K in keyof T > (obj: T, key: K): any => {
// return obj[key]
// }
type Person<T> = {
[K in keyof T]: T[K] // 在这里K是一个字符串类型的,而不是一个联合类型
}
const key1= "name"
prop(person, key1 as MiniPerson)
prop(person , key1 as LargePerson)