“字符串”不能用于索引类型“ {}”

时间:2019-08-04 20:42:21

标签: javascript reactjs typescript

我有以下React组件,该组件根据对象数组生成HTML表。通过import webbrowser a_website = "https://www.google.com" # Open url in a new window of the default browser, if possible webbrowser.open_new(a_website) # Open url in a new page (“tab”) of the default browser, if possible webbrowser.open_new_tab(a_website) webbrowser.open(a_website, 1) # Equivalent to: webbrowser.open_new(a_website) webbrowser.open(a_website, 2) # Equivalent to: webbrowser.open_new_tab(a_website) 属性定义应显示的列。

在遍历tableColumns并显示正确的列时,我必须使用items对象(key)的tableColumn属性,但打字稿会产生以下错误:

  

元素隐式地具有“ any”类型,因为类型“ string”的表达式不能用于索引类型“ {}”。     在类型“ {}”上找不到参数类型为“字符串”的索引签名。

该如何解决?我迷路了

我如何称呼该组件:

{item[column.key]}

我的组件:

<TableGridView
  items={[
    {
      id: 1,
      name: 'John Doe',
      email: 'john@doe.de'
    },
    {
      id: 2,
      name: 'Lorem ipsum',
      email: 'lorem@ipsum.com',
    }
  ]}
  tableColumns={[
    {
      key: 'id',
      label: 'ID',
    },
    {
      key: 'name',
      label: 'Name',
    }
  ]}
/>

6 个答案:

答案 0 :(得分:7)

  items: object[],

那只是一个不好的类型。相反,请准确输入,例如:

 items: {
   [key: string]: number | string,
  }[]

答案 1 :(得分:5)

使用泛型

// bad
const _getKeyValue = (key: string) => (obj: object) => obj[key];

// better
const _getKeyValue_ = (key: string) => (obj: Record<string, any>) => obj[key];

// best
const getKeyValue = <T extends object, U extends keyof T>(key: U) => (obj: T) =>
      obj[key];

错误-错误的原因是object类型默认情况下只是一个空对象。因此,不可能使用string类型来索引{}

更好-错误消失的原因是因为现在我们告诉编译器obj参数将是字符串/值(string/any)对的集合。但是,我们使用的是any类型,所以我们可以做得更好。

最佳-T扩展空对象。 U扩展了T的键。因此U将始终存在于T上,因此可以用作查找值。

以下是完整示例:

我已更改了泛型的顺序(U extends keyof T现在位于T extends object之前),以强调泛型的顺序并不重要,您应该选择对您的功能最有意义的顺序。

const getKeyValue = <U extends keyof T, T extends object>(key: U) => (obj: T) =>
  obj[key];

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Smith",
  age: 20
};

const getUserName = getKeyValue<keyof User, User>("name")(user);

// => 'John Smith'

答案 2 :(得分:5)

如果这是一个脚的javascript对象,没有必要为每个字段创建类型定义,并且也没有类定义的含义,则可以使用any键入对象,而typescript会让您随便索引。

例如。

//obviously no one with two brain cells is going to type each field individually
let complicatedObject: any = {
    attr1: 0,
    attr2: 0,
    ...
    attr999: 0
}

Object.keys(complicatedObject).forEach(key => {
    complicatedObject[key] += 1;
}

答案 3 :(得分:4)

首先,将 items 的类型定义为 objects 的数组是一个坏主意,因为它违背了 Typescript 的目的。而是定义数组将包含什么类型的对象。我会这样做:

type Item = {
  id: number,
  name: string,
  email: string,
}

export type TableGridViewProps = {
  items: Item[],
  tableColumns: TableColumn[]
};

之后,如果您绝对确定 key 将存在于 item 中,您可以执行以下操作来告诉 Typescript 您正在访问一个有效的索引。

<td
  key={column.key}
  className="lorem ipsum"
>
  {item[column.key as keyof typeof Item]}
</td>

答案 4 :(得分:0)

尝试更改:

  items={[
    {}
  ]}

收件人:

  items=[
    {}
  ]

这是假定的输出吗?

1
John Doe
2
Lorem ipsum

我明白了。

答案 5 :(得分:-2)

尝试添加类型any []

items:any[]