为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,我仍然收到相同的错误。
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;
发生这种情况是因为您尝试plotOptions使用string 访问属性name。TypeScript理解它name可能具有任何值,不仅是来自的属性名称plotOptions。因此,TypeScript需要向其中添加索引签名plotOptions,因此它知道您可以在中使用任何属性名称plotOptions。但我建议更改的类型name,因此它只能是plotOptions属性之一。
plotOptions
name
interface trainInfo { name: keyof typeof plotOptions; x: Array<number>; y: Array<number>; type: string; mode: string; }
现在,您将只能使用中存在的属性名称plotOptions。
您还必须稍微更改代码。
首先将数组分配给一些临时变量,因此TS知道数组类型:
const plotDataTemp: 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" }, // ... }
然后过滤:
const plotData = plotDataTemp.filter(({ name }) => plotOptions[name]);
如果您要从API获取数据并且无法在编译时键入检查道具,则唯一的方法是在您的索引中添加索引签名plotOptions:
type tplotOptions = { [key: string]: boolean } const plotOptions: tplotOptions = { train_1: true, train_2: true, train_3: true, train_4: true }