programing

Type Script:형식에 인덱스 서명이 없습니다.

css3 2023. 3. 31. 22:36

Type Script:형식에 인덱스 서명이 없습니다.

는 는고되 i i i want want i를 원한다.MyInterface.dicname: value뭇매를 맞다

interface MyInterface {
    dic: { [name: string]: number }
}

이제 내 유형을 기다리는 함수를 만듭니다.

function foo(a: MyInterface) {
    ...
}

그리고 입력:

let o = {
    dic: {
        'a': 3,
        'b': 5
    }
}

하고 있다foo(o)컴파일러가 다운되고 있습니다.

foo(o) // TypeScript error: Index signature is missing in type { 'a': number, 'b': number }

수 있다는 것을 있습니다.let o: MyInterface = { ... }TypeScript가 내 타입을 인식하지 못하는 이유는 무엇입니까?


추가: 다음과 같은 경우 정상적으로 동작합니다.o : is is is is is is is is is 。

foo({
  dic: {
    'a': 3,
    'b': 5
  }
})

때 ''이 '유형'이라는입니다.o 말합니다

{ dic: { a: number, b: number } }

건지같 와 같지 .{ dic: { [name: string]: number } } 중요한 것은 맨 o.dic['x'] = 1두 번째 서명으로.

실행 시 동일한 유형(실제로 동일한 값)이지만, TypeScript의 안전성의 큰 부분은 이러한 유형이 동일하지 않다는 사실과 개체를 사전으로 취급하도록 명시적으로 의도된 경우에만 허용한다는 사실에서 비롯됩니다.이로 인해 객체에 전혀 존재하지 않는 속성을 실수로 읽고 쓸 수 없게 됩니다.

해결책은 TypeScript가 사전으로서 의도된 것임을 확실히 하는 것입니다.즉, 다음과 같습니다.

  • 사전임을 나타내는 유형을 명시적으로 제공:

    let o: MyInterface

  • 사전 인라인이라고 단언하는 방법:

    let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }

  • TypeScript가 제공하는 초기 유형을 확인합니다.

    foo({ dic: { 'a': 1, 'b': 2 } })

만약 TypeScript가 2개의 속성만을 가진 일반 오브젝트라고 생각하고 나중에 사전으로 사용하려고 한다면, 그것은 좋지 않을 것입니다.

TS는 우리가 지수의 종류를 정의하기를 원합니다.예를 들어, 컴파일러에 임의의 문자열로 오브젝트를 인덱싱할 수 있음을 알립니다.myObj['anyString'] , 경::

interface MyInterface {
  myVal: string;
}

대상:

interface MyInterface {
  [key: string]: string;
  myVal: string;
}

이제 임의의 문자열 인덱스에 임의의 문자열 값을 저장할 수 있습니다.

x['myVal'] = 'hello world'
x['any other string'] = 'any other string'

놀이터 링크

저는 인터페이스 대신 타입을 사용하여 오류를 해결했습니다.

는 함수 '이러면 안 돼요'가할 수 .foo에는 다음과 같은 입력 파라미터의 인터페이스 대신 타입이 있습니다.

type MyType {
   dic: { [name: string]: number }
}

function foo(a: MyType) {}

그러나 전달된 값은 다음과 같은 인터페이스로 입력됩니다.

interface MyInterface {
    dic: { [name: string]: number }
}

const o: MyInterface = {
    dic: {
        'a': 3,
        'b': 5
    }
}

foo(o) // type error here

그냥 사용했어요

const o: MyType = {
    dic: {
        'a': 3,
        'b': 5
    }
}

foo(o) // It works

는 이렇게 할 수 요.foo({...o})

제, 냥, 냥, 냥, 냥을 거였어요.typeinterface.

제 의견은 이렇습니다.

type Copy<T> = { [K in keyof T]: T[K] }

genericFunc<SomeType>() // No index signature

genericFunc<Copy<SomeType>>() // No error

이 오류는 정당한 것입니다.대신 다음 코드를 작성하여 유형을 불변으로 표시해야 합니다.

interface MyInterface {
    dic: { [name: string]: number }
}

function foo(a: MyInterface) {
    ...
}

const o = Object.freeze({
    dic: {
        'a': 3,
        'b': 5
    }
})

왜요?

는 TypeScript가 음음음음음음음음음 that that the the the the that that that that 라고 가정할 수 .o과 시간 에 foo(o)출됩니니다다

코드 어딘가에 다음과 같은 내용이 적혀 있을 수 있습니다.

delete o.dic.a;

이것이 인라인 버전이 작동하는 이유입니다.이 경우 업데이트는 불가능합니다.

다음의 간단한 트릭도 도움이 될 수 있습니다.

type ConvertInterfaceToDict<T> = {
  [K in keyof T]: T[K];
};

이 변환은 문제를 해결하는 데 도움이 되었습니다.

'QueryParameters' 형식의 인수는 'Record<string, string> 유형의 매개 변수에 할당할 수 없습니다.

여기서 QueryParameters는 인터페이스입니다.서드파티 패키지로 직접 수정하지 못했습니다.

이 문제는 OP의 질문보다 조금 더 광범위합니다.

예를 들어 인터페이스의 인터페이스와 변수를 정의합니다.

interface IObj {
  prop: string;
}

const obj: IObj = { prop: 'string' };

''를 할당할 수 요?objRecord<string, string>

대답은 '아니오'입니다.데모

// TS2322: Type 'IObj' is not assignable to type 'Record<string, string>'. Index signature for type 'string' is missing in type 'IObj'.
const record: Record<string, string> = obj; 

왜 이런 일이 일어나는 거죠?이를 설명하기 위해 "업캐스팅"과 "다운캐스팅" 용어에 대한 이해와 SOLID 원칙에서 "L"자의 의미가 무엇인지 다시 한 번 살펴보겠습니다.

다음 예시는 "wider" 유형을 보다 엄격한 유형에 할당하기 때문에 오류 없이 작동합니다.

데모

const initialObj = {
  title: 'title',
  value: 42,
};

interface IObj {
  title: string;
}

const obj: IObj = initialObj; // No error here

obj.title;
obj.value; // Property 'value' does not exist on type 'IObj'.(2339)

IObj하나의 소품만 필요하기 때문에 할당은 정확합니다.

타입도 마찬가지입니다.데모

const initialObj = {
  title: 'title',
  value: 42,
};

type TObj = {
  title: string;
}

const obj: TObj = initialObj; // No error here

obj.title;
obj.value; // Property 'value' does not exist on type 'TObj'.(2339)

마지막 두 예는 "업캐스트" 때문에 오류 없이 작동합니다.즉, 값 유형을 "위" 유형, 즉 상위 유형일 수 있는 엔티티 유형으로 캐스팅합니다.즉, 개를 동물에게 할당할 수는 있지만 동물을 개에게 할당할 수는 없습니다(솔리드 원칙에서 "L"자의 의미 참조).개를 동물에게 할당하는 것은 "업캐스트"이며 이는 안전한 작업입니다.

Record<string, string>하나의 속성을 가진 물체보다 훨씬 넓습니다.을 사용하다

const fn = (record: Record<string, string>) => {
  record.value1;
  record.value2;
  record.value3; // No errors here
}

때문에 '아예'를 붙일 때 '아예'를 붙일 때IObj""에 대한 Record<string, string>에러가 표시됩니다.확장되는 유형에 할당합니다.IObjRecord<string, string>은 형은 の antant の antantantantant의 수.IObj.

다른 답변에서는 Type을 사용하면 문제를 해결할 수 있다고 언급되어 있습니다.하지만 나는 그것이 잘못된 행동이고 우리는 그것을 사용하는 것을 피해야 한다고 생각한다.

예:

type TObj = {
  title: string;
}

const obj: TObj = {
  title: 'title',
};


const fn = (record: Record<string, string>) => {
  record.value1;
  record.value2;
  // No errors here because according to types any string property is correct
  record.value3; 
}

fn(obj); // No error here but it has to be here because of downcasting

추신.

문제를 관련 질문과 흥미로운 코멘트로 살펴보십시오.

이것이 검색어 상위 결과인 것 같습니다.(string, string)이 있는 인덱스 유형이 이미 있고 해당 입력 유형을 변경할 수 없는 경우 다음을 수행할 수도 있습니다.

foo({...o}) // Magic

또 다른 방법은 다음과 같습니다.

interface MyInterface {
    [name: string]: number
}

function foo(a: MyInterface) {
    ...
}

let o = {
   'a': 3,
   'b': 5
}

foo(o);

언급URL : https://stackoverflow.com/questions/37006008/typescript-index-signature-is-missing-in-type