keyof用法
keyof是索引类型查询操作符。
假设T是一个类型,那么 keyof T产生的类型是T的属性名称所构成的联合类型。
type Props = {color?: string; age: number}type demo = keyof Props;// demo = 'color' | 'age'type demo = keyof Props[];// demo = number | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | ... 14 more ... | "includes"
也可以操纵类:
class Person{
name: string;
age: number;
}
type demo1 = keyof Person; // 'name' | 'age'
type demo2 = keyof Person[]; // 同上访问数组的类型
也支持基本数据类型;
type k1 = keyof boolean;
// k1 = 'valueOf'
type k2 = keyof string;
// k2 = number | "toString" | "charAt" | "charCodeAt" | "concat" 等等...
type k3 = keyof number;
// k3 = "toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"
此外,keyof 也称为输入索引类型查询,也称为查找类型。
在语法上我们看起来像是属性的访问,单最终会被转换为类型;
// 这里我们引用上面的Person类
type k1 = Person['name'] // 'string'
type k2 = Person['name' | 'age'] // 'string' | 'number'
typeof
typeof 用于获取变量的类型。在ts中这个操作符后面始终是一个变量。
const Person = {name: 'my name', age: 18};
type P = typeof Person; // type P = {name: string; age: number}
type P1 = keyof typeof Person; // type P1 = 'name' | 'age'
思维延伸
此前因为始终不能理解 utility-types 的工具源码实现,这里解释一下这个方法的具体实现步骤。
export type RequiredKeys<T extends object> = {
[P in keyof T]-?: {} extends Pick<T, P> ? never : P
}[keyof T]
我们以 RequiredKeys 为案例,从文章中我们知道用法:
type demo = RequiredKeys<{color?: string; age: number, b: boolean}>
// type demo = 'age' | 'b'
但是怎么只取 key 的呢?ts中又是怎么遍历的呢?
让我们来看下面的示例:
// 理解方法
{color?: string, age: number, s: number}['color' | 'age' | 's']
// 这里会索引类型
// 这样我们就得到了 string | number | undefined
综合以上知识,我们再来分析源码:
// 假设 T = {color?: string, age: number, s: number}
// 分析步骤
1、{ [P in keyof T]: P; }[keyof T]
2、{ [P in keyof T]: P; }['color' | 'age' | 's']
3、{color?: 'color', age: 'age', s: 's'}['color' | 'age' | 's']
// 返回 'color' | 'age' | 's' | undefined
通过上面的示例,我们大概知道了 {}[keyof] 的具体实现了吧。
想完全实现 RequiredKeys ,还要用 -? 强制转换为必选,去掉undefined,再用 Pick 过滤掉,就可以得到想要的效果了。
