Skip to content

TypeScript高级类型(三):索引类型

Published: at 12:16

索引类型可以把一个对象类型的所有公共的 key 联合起来形成联合类型。首先介绍一下与索引类型有关的一些知识。

keyof 关键字

keyof关键字是索引类型的查询操作符。索引类型主要通过 keyof 关键字来声明,它作用于一个对象类型。来看下面 🌰:

interface Obj {
  a: number;
  b: number;
}
let keys: keyof Obj;

此时keys的的类型是 Obj 属性的联合类型,也就是'a' | 'b',所以说keys的值只能是'a' | 'b'这两个。

T[K]

T[K]这种形式是索引访问操作符,表示对象 T 的属性 K 所代表的的类型。就拿上面的 Obj 接口来说,例如:

let value: Obj["a"];

此时value的类型就是 number 类型。

那么它们有什么用呢?

来看下面一段代码

let obj = {
  a: 1,
  b: 2,
  c: 3,
};
function getValues(obj: any, keys: string[]) {
  return keys.map(key => obj[key]);
}

上面写了一个getValues函数,传进去一个对象和一个 string 数组,所用是拿到 keys 的 item 作为 obj 的 key 的 value 值。

当我们开始使用的时候。

getValues(obj, ["a", "b"]);
getValues(obj, ["e", "f"]);

我们会发现ef都不是obj上的属性传进去没有被警告,TypeScript 本身就是为我们提供严格的类型约束,这种现象是不能忍受的,此时的解决办法就可以用到索引类型。

下面是我用索引类型约束好的代码。

function getValues<T, K extends keyof T>(obj: T, keys: K[]): T[K][] {
  return keys.map(key => obj[key]);
}

代码中使用了泛型约束K extends keyof T,意思是 K 泛型只能取T泛型的所用公共属性的key作为类型。其返回值是在obj中所查询到的值因此使用索引访问操作符来约束返回值类型数组。

此时我们再调用getValues函数就会对没有的属性进行约束。

getValues(obj111, ["a", "b"]); //✅
getValues(obj111, ["e", "f"]); //❌