keyof 类型操作符

简单来看就是获取key值的一个联合,如果是索引签名,则直接返回这些类型

数字字面量联合类型

keyof 也可能返回一个数字字面量的联合类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const NumericObject = {
[1]: "冴羽一号",
[2]: "冴羽二号",
[3]: "冴羽三号"
};

type result = keyof typeof NumericObject

// typeof NumbericObject 的结果为:
// {
// 1: string;
// 2: string;
// 3: string;
// }
// 所以最终的结果为:
// type result = 1 | 2 | 3

Symbol

TypeScript 也可以支持 symbol 类型的属性名

1
2
3
4
5
6
7
8
9
10
11
const sym1 = Symbol();
const sym2 = Symbol();
const sym3 = Symbol();

const symbolToNumberMap = {
[sym1]: 1,
[sym2]: 2,
[sym3]: 3,
};

type KS = keyof typeof symbolToNumberMap; // typeof sym1 | typeof sym2 | typeof sym3

所以有时候在使用字符串类型时会报错,因为无法指定symbol为string
如果确定只使用字符串类型的属性名,可以这么写

1
2
3
function useKey<T, K extends Extract<keyof T, string>>(o: T, k: K) {
var name: string = k; // OK
}

或者使用联合类型去处理


对于keyof的一些疑问

当想要获取Map类型的key值组成的时候,该如何操作?

1
2
3
4
const map1: Map<object, string> = new Map();
const a = { key: "object" };
type map = keyof typeof map1;
// type map = keyof Map<object, string>

上述操作会产生问题,即无法拿到Map内key值的类型

搜索后发现ts没有对这块做处理,但是可以手动实现

1
2
3
4
5
6
type KeyOfMap<M extends Map<unknown, unknown>> = M extends Map<infer K, unknown>
? K
: never;

type map = KeyOfMap<Map<object, string>>;
// type map = object

参考:ES Map 类型的 keyof 等价物什么

作者

徐云飞

发布于

2022-10-26

更新于

2023-02-05

许可协议

评论