programing

타이프스크립트:유형 '{A": 문자열;}에서 매개 변수 유형이 'string'인 인덱스 서명을 찾을 수 없습니다.

bestcode 2022. 9. 25. 00:29
반응형

타이프스크립트:유형 '{A": 문자열;}에서 매개 변수 유형이 'string'인 인덱스 서명을 찾을 수 없습니다.

문자열 입력을 받아 문자열을 문자로 분할한 후 오브젝트 상의 키에 일치시키는 바닐라 자바스크립트 코드를 가지고 있습니다.

DNATranscriber = {
    "G":"C",
    "C": "G",
    "T": "A",
    "A": "U"
}
function toRna(sequence){
    const sequenceArray = [...sequence];
    const transcriptionArray = sequenceArray.map(character =>{
        return this.DNATranscriber[character];
    });

    return transcriptionArray.join("");
}

console.log(toRna("ACGTGGTCTTAA")); //Returns UGCACCAGAAUU

이것은 예상대로 동작합니다.이제 이것을 타이프 스크립트로 변환하겠습니다.

class Transcriptor {
    DNATranscriber = {
       G:"C",
       C: "G",
       T: "A",
       A: "U"
    }
    toRna(sequence: string) {
        const sequenceArray = [...sequence];
        const transcriptionArray = sequenceArray.map(character =>{
            return this.DNATranscriber[character];
        });
    }
}

export default Transcriptor

하지만 다음과 같은 오류가 발생합니다.

유형 'string' > 의 식은 유형 '{A": string; }' 의 인덱스에 사용할 수 없기 때문에 요소에 암묵적인 유형이 있습니다.유형 >''문자열'' 매개 변수를 가진 인덱스 서명을 찾을 수 없습니다. {"A": 문자열; }.'ts(7053)

오브젝트 키가 문자열이어야 한다는 것이 문제라고 생각했습니다.하지만 그것들을 현으로 변환하는 것은 효과가 없었다.

DNATranscriber = {
       "G":"C",
       "C": "G",
       "T": "A",
       "A": "U"
    }

나는 이것 때문에 꽤 혼란스럽다.오브젝트에 문자열의 종류가 있는 인덱스 시그니처가 존재하지 않는다고 표시됩니다.하지만 그럴 거라고 확신해요.내가 뭘 잘못하고 있지?

편집 - 이 문제를 해결하려면 DNATransscriber 개체에 any 유형을 지정합니다.

DNATranscriber: any = {
    "G":"C",
    "C":"G",
    "T":"A",
    "A":"U"
}

또, 다음과 같이 할 수 있습니다.

(this.DNATranscriber as any)[character];

편집.

오브젝트를 적절한 타입으로 캐스팅하는 것이 좋습니다.any. 건을캐캐캐캐캐캐any를 컴파일 할 때 할 수 뿐, 를 이 되지 않습니다.

예.

interface DNA {
    G: "C",
    C: "G",
    T: "A",
    A: "U"
}

그리고 이렇게 던집니다.

(this.DNATranscriber as DNA)[character];

입력 내용을 확인함으로써 오류를 수정할 수 있습니다.이것은, 어떠한 경우에도 실시할 필요가 있습니다.

다음 형식 보호 검증을 통해 올바른 형식 검사를 수행합니다.

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};

export default class Transcriptor {
    toRna(dna: string) {
        const codons = [...dna];
        if (!isValidSequence(codons)) {
            throw Error('invalid sequence');
        }
        const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
        return transcribedRNA;
    }
}

function isValidSequence(values: string[]): values is Array<keyof typeof DNATranscriber> {
    return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

JavaScript를 TypeScript로 변환하려면 클래스를 사용해야 한다는 오해를 받고 있는 것 같습니다.

다음 좀 더 관용적인 버전에서는 TypeScript를 활용하여 구현 변경 없이 기본 쌍 매핑의 명확성을 높이고 보다 강력한 타이핑을 얻을 수 있습니다. '어울리다'를 .function한 일이야 정적 .JavaScript TypeScript 。

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};

export default function toRna(dna: string) {
    const codons = [...dna];
    if (!isValidSequence(codons)) {
        throw Error('invalid sequence');
    }
    const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function isValidSequence(values: string[]): values is Array<keyof typeof DNATranscriber> {
    return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

업데이트:

TypeScript 3.7 이후, 어설션 서명을 사용하여 입력 검증과 유형 함축 간의 대응 관계를 공식화함으로써 이를 보다 표현적으로 작성할 수 있습니다.

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
} as const;

type DNACodon = keyof typeof DNATranscriber;
type RNACodon = typeof DNATranscriber[DNACodon];

export default function toRna(dna: string): RNACodon[] {
    const codons = [...dna];
    validateSequence(codons);
    const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function validateSequence(values: string[]): asserts values is DNACodon[] {
    if (!values.every(isValidCodon)) {
        throw Error('invalid sequence');    
    }
}
function isValidCodon(value: string): value is DNACodon {
    return value in DNATranscriber;
}

어설션 시그니처에 대한 자세한 내용은 TypeScript 3.7 릴리즈 노트를 참조하십시오.

이것이 나의 관련된 문제를 해결하기 위해 한 일이었다.

interface Map {
  [key: string]: string | undefined
}

const HUMAN_MAP: Map = {
  draft: "Draft",
}

export const human = (str: string) => HUMAN_MAP[str] || str

간단한 타입스크립트와 관용 타입스크립트의 2가지 옵션이 있습니다.

  1. 인덱스 유형 사용
DNATranscriber: { [char: string]: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U",
};

오류 메시지가 나타내는 인덱스시그니처입니다레퍼런스

  1. 각 속성을 입력합니다.
DNATranscriber: { G: string; C: string; T: string; A: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U",
};

아무 것도 사용하지 말고 제네릭을 사용

// 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을 사용하다 UT.그러므로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];

이것으로 에러가 해소되어 타입이 세이프합니다.

this.DNATranscriber[character as keyof typeof DNATranscriber]

★★★★★★★★★★★★★★★★★★★★★★★에params요.keyOf Object.

interface User {
    name: string
    age: number 
}

const user: User = {
    name: "someone",
    age: 20
}

function getValue(key: keyof User) {
    return user[key]
}

같은 문제를 다음과 같이 해결:

export interface IItem extends Record<string, any> {
    itemId: string;
    price: number;
}

const item: IItem = { itemId: 'someId', price: 200 };
const fieldId = 'someid';

// gives you no errors and proper typing
item[fieldId]

도 비슷한 했습니다.getClass뭇매를 맞다

import { ApiGateway } from './api-gateway.class';
import { AppSync } from './app-sync.class';
import { Cognito } from './cognito.class';

export type stackInstances = typeof ApiGateway | typeof  AppSync | typeof Cognito

export const classes = {
  ApiGateway,
  AppSync,
  Cognito
} as {
  [key: string]: stackInstances
};

export function getClass(name: string) {
  return classes[name];
}

의 내력을 입력하다classes내 유니언 타입의 활자본을 행복하게 만들어줘서 그게 말이 돼.

예를 들어 Record를 사용할 수 있습니다.

let DNATranscriber: Record<string, string> = {};

Google 사용자:

형식에서 매개 변수가 'string'인 인덱스 서명을 찾을 수 없습니다...

대부분의 경우 오류는 다음과 같습니다.

요?keyof Numberstring

비슷한 타이핑 문제를 다음과 같은 코드로 해결했습니다.

const stringBasedKey = `SomeCustomString${someVar}` as keyof typeof YourTypeHere;

이슈는 오류의 진정한 의미를 이해하는 데 도움이 되었습니다.

이게 너한테 더 도움이 될 것 같아.

이 기능을 사용하면 인수를 입력할 때 제안사항을 얻을 수 있으며(편집기에서 시도), 나중에 사용할 수 있도록 강력한 반환 유형을 얻을 수 있습니다.

제안 스크린샷

또한 Aluan Haddad의 답변에서 영감을 받아 시퀀스 검증이 이루어지지만 텍스트 루프 내에서 검증이 이루어지기 때문에 좀 더 효율적입니다.

type DNAletter = 'G' | 'C' | 'T' | 'A';
type RNAletter = 'C' | 'G' | 'A' | 'U';

const DNATranscriber: { [key in DNAletter]: RNAletter } = {
  G: 'C',
  C: 'G',
  T: 'A',
  A: 'U'
};

// Return `RNAletter[]`
function toRna(sequence: string | string[] | DNAletter[]) {
  return ([...sequence] as DNAletter[]).map(character => {
    const transcribed = DNATranscriber[character];
    if (transcribed === undefined)
      throw Error(`Invalid character "${character}" in sequence`);
    return transcribed;
  });
}

편집: TS3.4 이후로는 const로 사용할 수 있습니다.

한동안 이걸 가지고 놀았거든요.제 시나리오는 다음과 같습니다.

metrics1과 metrics2의 두 가지 유형이 있으며 각각 다른 속성을 가집니다.

type metrics1 = {
    a: number;
    b: number;
    c: number;
}

type metrics2 = {
    d: number;
    e: number;
    f: number;
}

이 오브젝트에는 모든 속성이 저장되어 있기 때문에 코드의 어느 시점에서 이 두 유형의 교차점에 있는 오브젝트를 만들었습니다.

const myMetrics: metrics1 & metrics2 = {
    a: 10,
    b: 20,
    c: 30,
    d: 40,
    e: 50,
    f: 60
};

이제 해당 개체의 속성을 동적으로 참조해야 합니다.여기서 인덱스 서명 오류가 발생합니다.컴파일 시간 체크와 런타임 체크를 기반으로 문제의 일부를 분석할 수 있습니다.const를 사용하여 객체를 참조하는 경우 TypeScript는 컴파일 중에 속성이 존재하는지 여부를 확인할 수 있기 때문에 이 오류는 표시되지 않습니다.

const myKey = 'a';
console.log(myMetrics[myKey]); // No issues, TypeScript has validated it exists

그러나 동적 변수(예를 들어 let)를 사용하는 경우 TypeScript는 컴파일 시간 동안 속성이 존재하는지 여부를 확인할 수 없으며 실행 시 추가 도움말이 필요합니다.여기서 다음 타입가드가 사용됩니다.

function isValidMetric(prop: string, obj: metrics1 & metrics2): prop is keyof (metrics1 & metrics2) {
    return prop in obj;
}

이는 "obj속성 프로포스트가 있는 경우 TypeScript에 메트릭스1과 메트릭스2의 교차점에 프로포트가 존재함을 알립니다."라고 쓰여 있습니다.주의: 위의 키 에 반드시 metrics1과 metrics2를 괄호로 둘러싸십시오.그렇지 않으면 metrics1의 키와 metrics2의 유형(키가 아님)이 교차합니다.

이제 typeguard를 사용하여 런타임 중에 개체에 안전하게 액세스할 수 있습니다.

let myKey:string = '';
myKey = 'a';
if (isValidMetric(myKey, myMetrics)) {
    console.log(myMetrics[myKey]);
}

저의 해결책은

type DNATranscriber = {
   G: string,
   C: string,
   T: string,
   A: string,
}
type DNATanscriberIndex = {
   [key: string]: string
}

let variableName:DNATanscriberIndex&DNATanscriber

DNATransscriber 타입은 Typescript가 필드 및 DNATanscriber를 참조할 수 있도록 하기 위한 것입니다.인덱스 유형은 인덱스를 문자열로 선언하는 것입니다.

다음은 어레이 개체의 일반적인 유형 트리밍 함수 예제입니다.

const trimArrayObject = <T>(items: T[]) => {

  items.forEach(function (o) {

    for (let [key, value] of Object.entries(o)) {

      const keyName = <keyof typeof o>key;

      if (Array.isArray(value)) {

        trimArrayObject(value);

      } else if (typeof o[keyName] === "string") {

        o[keyName] = value.trim();

      }

    }

  });

};

오브젝트 키를 사용하지 않고 이 문제를 해결할 수 있는 방법은 다음과 같습니다.

function toRna(value: string): string {
  return value.split('').map(ch => 'CGAU'['GCTA'.indexOf(ch)]).join('');
}

console.log(toRna('ACGTGGTCTTAA')); 
\\UGCACCAGAAUU

이렇게 반환 유형을 사용하여 얻을 수 있습니다.

getAllProperties(SellRent: number) : Observable<IProperty[]>{
return this.http.get<IProperty[]>('data/properties.json').pipe(
  map(data => {

    const propertiesArray: Array<IProperty> = [];
    for(const id in data){
      if(data.hasOwnProperty(id) && data[id].SellRent === SellRent){
        propertiesArray.push(data[id]);
      }
    }
    return propertiesArray;
  })
)

}

오래된 질문인 것은 알지만, TS는 질문을 받았을 때보다 문제를 쉽게 입력할 수 있는 방법을 제공합니다.TS3.4에서 가장 심플한 접근방식은 "항상"을 사용하는 것입니다.객체를 입력하는 것은 결코 올바른 솔루션 IMO가 아닙니다.

DNATranscriber = {
    "G":"C",
    "C": "G",
    "T": "A",
    "A": "U"
} as const;

이는 이제 ts가 이러한 키와 값이 변경되지 않는다는 것을 알았으므로 유추로 평가할 수 있음을 의미합니다.즉, TS는 이미 그 DNATransscriber를 인식하고 있습니다.G]가 "C"가 되어 출력 코드를 체크할 수 있습니다.이것은, 한층 더 도움이 됩니다.

지난 이야기...Marias의 답변과 같다.

type Keys = "G" | "C" | "T" | "A";
type values "C" | "G" | "A" | "U";
DNATranscriber: {[K in Keys]: values} = {
    "G":"C",
    "C": "G",
    "T": "A",
    "A": "U"
};

매핑의 정적 특성을 나타내지 않았기 때문에 이상적이지 않습니다.

간단한 해결 방법은 다음과 같습니다.

(obj as { [k in string]: any })[key]
const Translator : { [key: string]: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U"
 }
 
 export function toRna(DNA:string) {

   const Translate = [...DNA];
   let Values = Translate.map((dna) => Translator[dna])
   if (Validate(Values)) {return Values.join('')}
 }

export function Validate(Values:string[]) : Boolean{
 if (Values.join('') === "" || Values.join('').length !== Values.length) throw Error('Invalid input DNA.');
 return true
}

유사한 사례로 어려움을 겪고 있는 모든 분들을 위해

No index signature with a parameter of type 'string' was found on type X

다음과 같은 단순한 오브젝트(dict로 사용)와 함께 사용하려고 합니다.

DNATranscriber = {
   G:"C",
   C: "G",
   T: "A",
   A: "U"
}

다음과 같이 계산된 키에서 값에 동적으로 액세스하려고 합니다.

const key = getFirstType(dnaChain);
const result = DNATranscriber[key];

그리고 당신은 위와 같은 에러를 직면했고, 당신은 연산자 를 사용하여 다음과 같은 것을 시도할 수 있습니다.

const key = getFirstType(dnaChain) as keyof typeof DNATranscriber;

result다만, 커스텀 타입의 마법보다 직관적으로 느껴진다면 괜찮습니다.

언급URL : https://stackoverflow.com/questions/56568423/typescript-no-index-signature-with-a-parameter-of-type-string-was-found-on-ty

반응형