尝试一个React项目的TypeScript,我被这个错误困住了:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ train_1: boolean; train_2: boolean; train_3: boolean; train_4: boolean; }'.
  No index signature with a parameter of type 'string' was found on type '{ train_1: boolean; train_2: boolean; train_3: boolean; train_4: boolean; }'

当我试图在我的组件中过滤数组时出现

.filter(({ name }) => plotOptions[name]);

到目前为止,我查看了文章“在TypeScript中索引对象”(https://dev.to/kingdaro/indexing-objects-in-typescript-1cgi),因为它有类似的错误,但我尝试将索引签名添加到类型plotTypes,我仍然得到相同的错误。

我的组件代码:

import React, { Component } from "react";
import createPlotlyComponent from "react-plotly.js/factory";
import Plotly from "plotly.js-basic-dist";
const Plot = createPlotlyComponent(Plotly);

interface IProps {
  data: any;
}

interface IState {
  [key: string]: plotTypes;
  plotOptions: plotTypes;
}

type plotTypes = {
  [key: string]: boolean;
  train_1: boolean;
  train_2: boolean;
  train_3: boolean;
  train_4: boolean;
};

interface trainInfo {
  name: string;
  x: Array<number>;
  y: Array<number>;
  type: string;
  mode: string;
}

class FiltrationPlots extends Component<IProps, IState> {
  readonly state = {
    plotOptions: {
      train_1: true,
      train_2: true,
      train_3: true,
      train_4: true
    }
  };
  render() {
    const { data } = this.props;
    const { plotOptions } = this.state;

    if (data.filtrationData) {
      const plotData: Array<trainInfo> = [
        {
          name: "train_1",
          x: data.filtrationData.map((i: any) => i["1-CumVol"]),
          y: data.filtrationData.map((i: any) => i["1-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_2",
          x: data.filtrationData.map((i: any) => i["2-CumVol"]),
          y: data.filtrationData.map((i: any) => i["2-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_3",
          x: data.filtrationData.map((i: any) => i["3-CumVol"]),
          y: data.filtrationData.map((i: any) => i["3-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_4",
          x: data.filtrationData.map((i: any) => i["4-CumVol"]),
          y: data.filtrationData.map((i: any) => i["4-PressureA"]),
          type: "scatter",
          mode: "lines"
        }
      ].filter(({ name }) => plotOptions[name]);
      return (
        <Plot
          data={plotData}
          layout={{ width: 1000, height: 1000, title: "A Fancy Plot" }}
        />
      );
    } else {
      return <h1>No Data Loaded</h1>;
    }
  }
}

export default FiltrationPlots;


当前回答

当我们做类似这样的事情时,obj[key] Typescript不能确定该键是否存在于该对象中。我做了什么:

Object.entries(data).forEach(item => {
    formData.append(item[0], item[1]);
});

其他回答

这就是它对我的作用。tsconfig。json有一个选项noImplicitAny,它被设置为true,我只是简单地将其设置为false,现在我可以使用字符串访问对象中的属性。

这不是对原来问题的回答,而是对这个问题的一般工作。

最初的问题: 人(cr。导致此错误


我正在做一个通用的高级搜索表单,用户可以选择一个字段,比较器和所需的值。当试图根据键从对象中读取值时,我得到这个错误(尽管字段值是字符串类型,我认为它应该是好的)

我所做的就是像这样提取[key, value]

const x: [string, any] = Object.entries(person).find(([key, _]) => key === cr.field);

例如,如果我的标准(cr)是{field: 'name', value: 'John'},字段名实际上存在于一个人obj中。,它应该返回字段名和值为tuple (x是[string, any]或undef)。如果没有找到,未定义。

我通过使用keyof修复了这个问题

messageMap = {
 "Hi": "Hello",
 "Who are you": "My name is Test Sat Bot",
 "What is your role": "Just guide for the user",
}

这❌

let answer = this.messageMap[question];

替换为✔️

let answer = this.messageMap[question as keyof typeof this.messageMap];

这里的问题是字符串的类型。

getBotMessage(question: string){    
  let answer = this.messageMap[question as keyof typeof this.messageMap];
}

作为最后的手段,你可以通过在tsconfig.json中设置"suppressImplicitAnyIndexErrors": true来消除这个错误

{
  "compilerOptions": {
    "suppressImplicitAnyIndexErrors": true,
  }
}

我对Alex McKay的函数/用法做了一些小改动,我认为这样可以让它更容易理解为什么它可以工作,同时也遵循了定义前不使用的规则。

首先,定义这个函数来使用:

const getKeyValue = function<T extends object, U extends keyof T> (obj: T, key: U) { return obj[key] }

在我写它的方式中,函数的泛型首先列出对象,然后是对象上的属性(这些可以以任何顺序出现,但如果你在T扩展对象之前指定U扩展T的key,你就打破了定义前不使用的规则,而且对象在前,属性在后也是有意义的。最后,我使用了更常用的函数语法,而不是箭头操作符(=>)。

不管怎样,通过这些修改,你可以像这样使用它:

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

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

getKeyValue(user, "name")

同样,我觉得这样更有可读性。