TypeScript 隐式索引类型签名

62 阅读1分钟

考虑定义如下 TypeScript 代码:

interface NumbersNames {
  [key: string]: string
}

const names: NumbersNames = {
  1: 'one',
  2: 'two',
  3: 'three',
  // etc...
}

虽然我们定义对象的 key 是数字,但对象会隐式转换为字符串的,当我们通过字符串索引,就能够得到正确的值:

const one = names['1']; // OK

如果通过数字索引呢,就像下面这样:

const two = names[2];

根据上面定义的类型我们知道,我们定义的索引签名是字符串,如果通过数字来进行索引,毫无疑问在 TypeScript 中是错误的。

但真实情况却不是这样,数字索引通过了 TS 的检查,这是为什么?

这是因为数字用作属性访问器中的键时,JavaScript 会隐式将数字强制转换为字符串(names[1]等价于names['1']),TypeScript 中也保留这个特性。

知道这个特性有什么用处呢,一个真实的场景是,你需要为一个变量定义类型,这个变量的类型既可以是数组又可以是对象,正常思路应该是这样的:

interface recordable<T = any> {
  [key: string | number]: T;
}

当·T = any·,并且你知道上面那个知识点就明白 number 是可以省略的。

interface recordable<T = any> {
  [key: string]: T;
}

参考: