TypeScript -元素隐式具有“any”类型,因为“string”类型的表达式不能用于索引类型

vmdwslir  于 2022-12-19  发布在  TypeScript
关注(0)|答案(4)|浏览(326)

我有这个代码:

const color = {
    red: null,
    green: null,
    blue: null
};

const newColor = ['red', 'green', 'blue'].filter(e => color[e]);

错误位于color[e]底部附近,错误为:
元素隐式具有"any"类型,因为"string"类型的表达式不能用于索引类型"{red:空;绿色:空;蓝色:null ;}"。在类型" {red:空;绿色:空;蓝色:空;}"。
我试着在TypeScript文档上到处找,但是我怎么才能interface它才能接受color[e]呢?

oprakyz7

oprakyz71#

您可以将colors声明为any,以告诉TypeScript不要再纠缠于此(也称为 explicit any):

const color : any = {
    red: null,
    green: null,
    blue: null
};

但如果可能,最好使用强类型:

const color : { [key: string]: any } = {
    red: null,
    green: null,
    blue: null
};

有关在TypeScript中编制索引的详细信息:Index Signatures

  • 编辑:* 在this answer中,对于类似的问题,作者建议使用Map<,>--如果它适合您的用例。
e5nqia27

e5nqia272#

您遇到的问题不是color是错误的类型,而是TypeScript将['red', 'green', 'blue']的类型推断为string[]。(对于编译器所知道的)您可能希望将'purple'推送到它上面。您希望编译器知道唯一的成员是三个字符串常量'red''green''blue',也就是说,您需要至少与Array<'red'|'green'|'blue'>一样具体的类型。
假设您使用的是TS3.4或更高版本,从编译器获得这种类型推断的最简单方法是使用constAssert:

const constAssertionTest = ["red", "green", "blue"] as const;
// const constAssertionTest: readonly ["red", "green", "blue"];

as const使编译器推断出一个由数组中的三个字符串常量组成的元组,顺序与您设置的顺序完全相同(它甚至是一个只读元组),这足以修复您的错误:

const newColor = (['red', 'green', 'blue'] as const).filter(e => color[e]); // okay

好吧,希望能帮上忙。祝你好运!
链接到代码

bcs8qyzn

bcs8qyzn3#

我知道这是一个老问题,但我不满意其他的答案。请尽量避免使用as关键字!
让我们看看为什么会遇到这个错误以及如何处理它。

原因:常量和字符串数组都没有类型。

当你不给常量一个类型时,Typescript会根据初始值来推断它的类型。知道了这一点,错误只会说"嘿,e可以是任何字符串,甚至是不属于常量的推断类型的字符串"。如果e等于'yellow',而'yellow'color的推断类型中是未知的,那该怎么办?
我可以向您推荐3种处理方法:

1.最简单但并非如此的"类型脚本精神"解决方案

只需为const的键指定一个类型string,如下所示:

const color: {[key:string]:null} = {
  red: null,
  green: null,
  blue: null
};

嗯......那很好,但我们可以做得更好。

2.在打字的路上...

告诉Typescript编译器,您正在使用const的推断类型的键和关键字:keyof typeof.
在给定的示例中,这将是:

const colorKeys: (keyof typeof color)[]  = ['red', 'green', 'blue'];

const newColor = colorKeys.filter((e) => color[e]);

你还能再努力一点吗?看下一点。

3.这是:给你的对象类型!

创建一个接口(或者任何你需要的类型)并把它赋给你的常量,然后用keyof关键字指定字符串数组的类型:

interface Color {
  red:number|null;
  green:number|null;
  blue:number|null;
}
const color: Color = {
  red: null,
  green: null,
  blue: null
};

const colorKeys: (keyof Color)[]  = ['red', 'green', 'blue'];

const newColor = colorKeys.filter((e) => color[e]);
mhd8tkvw

mhd8tkvw4#

感谢所有伟大的答案。新的 typescript ,并成功地修复了我的第一个路障。

// in javascript world this is what I used to do.
  let values1 = products.reduce((acc, product) => {
      acc[product] = 1;
  //  ^  --> Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  // No index signature with a parameter of type 'string' was found on type '{}'.  TS7053

      return acc;
  }, {})

  // in typescript world I needed an extract type specification for 'acc'
  let values2 = products.reduce((acc: { [key: string]: number}, product) => {
      acc[product] = 1; //No more error
      return acc;
  }, {})

相关问题