programing

'string' 형식의 표현식을 인덱싱에 사용할 수 없으므로 요소에 '임의' 형식이 암시적으로 있습니다.

telecom 2023. 3. 1. 09:31
반응형

'string' 형식의 표현식을 인덱싱에 사용할 수 없으므로 요소에 '임의' 형식이 암시적으로 있습니다.

리액트 프로젝트용 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]);

지금까지 기사 "Indexing objects in TypeScript"(https://dev.to/kingdaro/indexing-objects-in-typescript-1cgi)에서 비슷한 오류가 발생했기 때문에 참조했는데 인덱스 서명을 Type에 추가하려고 했습니다.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;

미래에 이 정보를 우연히 발견하게 될 사람을 위해:

TypeScript 오류가 표시되는 경우

'...문자열 형식을 인덱싱하는 데 사용할 수 없습니다..'

그런 다음 'type string'이 해당 개체 유형의 키임을 지정하기만 하면 됩니다.예를들면,

const someObj:ObjectType = data;
const field = 'username';

// This gives an error
const temp = someObj[field];

// Solution 1: When the type of the object is known
const temp = someObj[field as keyof ObjectType]

// Solution 2: When the type of the object is not known
const temp = someObj[field as keyof typeof someObj]

문제는 에 발생합니다.plotOptions을 사용한 name 을 인식합니다. 타이프 스크립트name에는 임의의할 수 속성명도 되어 있습니다.plotOptions는 TypeScript에 를 추가해야 합니다.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에 입니다.plotOptions:

type tplotOptions = {
    [key: string]: boolean
}

const plotOptions: tplotOptions = {
    train_1: true,
    train_2: true,
    train_3: true,
    train_4: true
}

「」를 사용하고 Object.keys, 다음과 같이 동작합니다.

Object.keys(this)
    .forEach(key => {
      console.log(this[key as keyof MyClass]);
    });

나는 이것을 사용한다.

interface IObjectKeys {
  [key: string]: string | number;
}

interface IDevice extends IObjectKeys {
  id: number;
  room_id: number;
  name: string;
  type: string;
  description: string;
}

메모: [key: string]" 이게 뭐죠?JavaScript의 개체는 주로 키와 값의 쌍으로 구성된 속성 모음입니다.또한 키는 문자열(어레이 요소의 경우에도)만 사용할 수 있지만 값은 모든 데이터 유형입니다.

개체에서 선택적 속성을 사용하는 경우:

interface IDevice extends IObjectKeys {
  id: number;
  room_id?: number;
  name?: string;
  type?: string;
  description?: string;
}

... IObjectKeys 인터페이스에 '정의되지 않은' 값을 추가해야 합니다.

interface IObjectKeys {
  [key: string]: string | number | undefined;
}
// 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];

Bad] : 은 [Bad] - [Bad]입니다.object일 뿐입니다.type은 빈 개체입니다. 때문에 이렇게 할 수 string{}.

Better - 오류가 사라지게 된 이유는 컴파일러에 다음 명령을 전달하기 때문입니다.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];

나는 그 문제의 시뮬레이션을 만들었다.Typescript의 괄호 표기법을 사용하여 오브젝트 속성에 동적으로 액세스하는 방법이 문제인 것 같습니다.

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

export default class User {
  constructor(private data: IUserProps) {}

  get(propName: string): string | number {
    return this.data[propName as keyof IUserProps];
  }
}

나는 이것을 더 잘 이해하는 데 도움이 될 만한 블로그를 찾았다.

링크 https://www.subsershamma.dev/dev/2019/how-to-access-object-properties-dynamic-using-dynamically-using-subject-in-typript/는 다음과 같습니다.

이 obj[key]와 같은 작업을 하면 타이프 스크립트는 해당 개체에 해당 키가 있는지 확실히 알 수 없습니다.내가 한 일:

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

없이.typescript에러

    const formData = new FormData();
    Object.keys(newCategory).forEach((k,i)=>{  
        var d =Object.values(newCategory)[i];
        formData.append(k,d) 
    })

를 사용하여 이 문제를 해결했습니다.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];

여기서question는 문자열 유형입니다.

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

Alex Mckay 덕분에 저는 역동적인 소품을 만들 결심을 했습니다.

  for(let prop in filter)
      (state.filter as Record<string, any>)[prop] = filter[prop];

저는 그게 잘 먹혔어요.keyof그리고.as연산자:

const keys: [keyof ITrainInfo] = Object.keys(this.trainInfo) as [
    keyof ITrainInfo,
]
keys.forEach((property) => {
    // console.log(tmpUser[property])
    if (this.trainInfo === undefined) return
    if (this.trainInfo[property] !== undefined) {
        // your code here
        /*const trainsToSet = trains.find((field) => field.name === property)
        if (trainsToSet != undefined)
            trainsToSet.value = this.trainInfo[property]?.toString()
        */
    }
})

저는 Alex McKay의 기능/사용법을 조금 변경했는데, 그 이유는 좀 더 쉽게 알 수 있고 정의 전 사용 안 함 규칙도 준수한다고 생각합니다.

먼저 이 함수를 정의하여 다음을 사용합니다.

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

내가 쓴 방법으로는 함수의 범용이 먼저 개체를 나열하고 다음으로 개체의 속성을 나열합니다(이러한 속성은 임의의 순서로 발생할 수 있습니다만, 지정한 경우).U extends key of T전에T extends object네가 부숴라no-use-before-define규칙, 그리고 대상을 먼저 가지고 그 속성을 두 번째로 갖는 것이 말이 됩니다.마지막으로 화살표 연산자 대신 일반적인 함수 구문을 사용했습니다.=>).

어쨌든, 이러한 변경에 의해, 다음과 같이 사용할 수 있습니다.

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

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

getKeyValue(user, "name")

다시 말씀드리지만 좀 더 읽기 쉽네요

TypeScript는 이러한 값이 trainInfo에 존재하는지 확인해야 합니다.그렇지 않으면 모두 문자열로 읽힙니다.

이렇게 하는 대신

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

이것을 하다

interface trainInfo {
  name: "train_1" | "train_2" | "train_3"| "train_4";
  x: Array<number>;
  y: Array<number>;
  type: string;
  mode: string;
}

이것은 원래 질문에 대한 답변이 아니라 이 문제에 대한 일반적인 회피책입니다.

원래 문제:person[cr.field]이 에러의 원인


사용자가 필드, 비교기 및 원하는 값을 선택할 수 있는 일반 고급 검색 양식을 만들고 있습니다.키를 기반으로 개체에서 값을 읽으려고 하면 이 오류가 발생합니다(예:field 저는 value가 합니다.

이렇게 [키, 값]을 추출합니다.

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

를 들어, 나의 「 」 「 」 「 」 )이 되는 경우.cr는 )개요{ field: 'name', value: 'John' } 필드 " " "name하는 경우 을 tuple로 해야 합니다(는 obj입니다[string, any]또는 정의되지 않음).을 사용하다

public get User Name(): 문자열 {

const accessToken = this.getAccessToken();
const claims:any = this.getUserClaims();
console.log('access token ',accessToken);
this.getUserInfo();
return claims['sub'].split('@')[0];

}

//변수에 임의의 유형 지정

으로 이 , 「음소거」를 합니다."suppressImplicitAnyIndexErrors": truetsconfig.json

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

조금 늦었다는 것을 알지만, 약간의 변환만 추가하면 됩니다.저는 올바른 타이핑으로 키 배열을 안전하게 돌려주는 정적 기능을 썼습니다.유형을 정의하고 객체를 매개 변수로 전달하기만 하면 됩니다.

export class ObjectUtil {
  public static getObjectKeys<T>(obj: Object) {
    if (!obj) {
      return [];
    }

    return Object.keys(obj).map((key: string) => key as keyof T);
  }
}

다음은 간단한 예입니다.

ObjectUtil.getObjectKeys<Address>(address).forEach((key) => {
  console.log(address[key]);
});

이게 나한테 효과가 있었어.tsconfig.jsonnoImplicitAny로 설정되었다.true 그냥 false이제 문자열을 사용하여 객체의 속성에 액세스할 수 있습니다.

언급URL : https://stackoverflow.com/questions/57086672/element-implicitly-has-an-any-type-because-expression-of-type-string-cant-b

반응형