Typescript:我是否必须检查数组以摆脱TS7053(可能的数组元素的字符串索引)

hfwmuf9z  于 2023-01-21  发布在  TypeScript
关注(0)|答案(2)|浏览(129)

我曾经遇到过这样一种情况,我认为遵守 typescript 检查会导致代码变慢。
下面是我的(过于简化的)函数:

function test(data: { [key: string]: any } | any[]) {
  const x = Object.keys(data).reduce((res: { [key: string]: any }, name: string) => {
    const item = data[name];
    const key = item?.name || name;
    ...
  });
}

基本上只是将数组或对象转换为对象-看起来像这样简化。2实际上它也确保项是正确的类类型。
无论如何,data[name]行生成TS 7053,因为-如果data是数组-访问器应该是Number
解决 typescript 警告的方法是将该行重写为:

const item = data instanceof Array ? data[Number(name)] : data[name];

然而,我相信这种解决方案比以前发生的隐式类型强制要慢,因为它首先检查类型、分支,然后才进行显式类型转换,最后才访问项。
我意识到,对于数组,更合适的解决方案是简单地使用Array.forEach,但这需要一个函数提取,以避免重复所讨论的代码,整个代码只有三行,其目的只是通过name属性索引项,以便更快地访问。
有没有更好的方法让TypeScript检查器满意?

qyuhtwio

qyuhtwio1#

你可以用Object.entries()代替Object.keys(),这样你就不必进行值查找,同时也解决了你的类型问题:

function test(data: { [key: string]: any } | any[]) {
  return Object.entries(data).reduce((a: { [key: string]: any }, [k, v]) => {
    a[v?.name || k] = v;
    return a;
  }, {});
}

Playground链接

icnyk63a

icnyk63a2#

数组也是一个对象,所以你可以简单地从类型签名中省略它:

function test(data: { [key: string]: any }) {
  const x = Object.keys(data).reduce((res: { [key: string]: any }, name: string) => {
    const item = data[name];
    const key = item?.name || name;
    res[key] = item;
    return res;
  }, {});
  console.log(x);
}

test([1, 2, 3]);               // { "0": 1, "1": 2, "2": 3 }
test({a: 'Alice', b: 'Bob'});  // { "a": "Alice", "b": "Bob" }

Playground链接
这是因为Object.keys总是以字符串的形式返回键,即使它们是数字数组键,还因为您还可以使用数字字符串来索引数组。
我还必须添加一个空对象{}作为reduce的初始值,否则它将获取第一个键,这是一个字符串而不是一个对象。

相关问题