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;
답변
이것은 plotOptions
string을 사용하여 속성 에 액세스하려고하기 때문에 발생 합니다 name
. TypeScript name
는의 속성 이름뿐만 아니라 모든 값을 가질 수 있음을 이해합니다 plotOptions
. 따라서 TypeScript는에 인덱스 서명을 추가해야하므로 .NET plotOptions
에서 모든 속성 이름을 사용할 수 있음을 알고 있습니다 plotOptions
. 그러나 유형을 변경하는 것이 name
좋으므로 plotOptions
속성 중 하나만 될 수 있습니다.
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에서 데이터를 가져오고 컴파일 타임에 check props를 입력 할 방법이없는 경우 유일한 방법은에 인덱스 서명을 추가하는 것입니다 plotOptions
.
type tplotOptions = {
[key: string]: boolean
}
const plotOptions: tplotOptions = {
train_1: true,
train_2: true,
train_3: true,
train_4: true
}
답변
// 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'
대체 구문
const getKeyValue = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];
답변
우리가 이런 일을 할 때 obj [key] Typescript는 그 키가 그 객체에 존재하는지 확실히 알 수 없습니다. 제가 한:
Object.entries(data).forEach(item => {
formData.append(item[0], item[1]);
});
답변
나는 이것을 사용한다 :
interface IObjectKeys {
[key: string]: string;
}
interface IDevice extends IObjectKeys {
id: number;
room_id: number;
name: string;
type: string;
description: string;
}
답변
를 사용 Object.keys
하면 다음이 작동합니다.
Object.keys(this)
.forEach(key => {
console.log(this[key as keyof MyClass]);
});
답변
밖으로 typescript
오류
const formData = new FormData();
Object.keys(newCategory).map((k,i)=>{
var d =Object.values(newCategory)[i];
formData.append(k,d)
})
답변
Alex Mckay 덕분에 저는 소품을 동적으로 설정하는 결심을했습니다.
for(let prop in filter)
(state.filter as Record<string, any>)[prop] = filter[prop];