program story

형식에 호출 서명이없는 식을 호출 할 수 없습니다.

inputbox 2020. 11. 25. 07:55
반응형

형식에 호출 서명이없는 식을 호출 할 수 없습니다.


나는 사과와 배가 있습니다-둘 다 isDecayed속성이 있습니다.

interface Apple {
    color: string;
    isDecayed: boolean;
}

interface Pear {
    weight: number;
    isDecayed: boolean;
}

그리고 두 유형 모두 내 과일 바구니에있을 수 있습니다 (여러 번).

interface FruitBasket {
   apples: Apple[];
   pears: Pear[];
}

지금 내 바구니가 비어 있다고 가정 해 보겠습니다.

const fruitBasket: FruitBasket = { apples: [], pears: [] };

이제 우리는 바구니에서 무작위로 한 종류를 꺼냅니다.

const key: keyof FruitBasket = Math.random() > 0.5 ? 'apples': 'pears'; 
const fruits = fruitBasket[key];

물론 썩은 과일을 좋아하는 사람은 아무도 없으므로 신선한 과일 만 선택합니다.

const freshFruits = fruits.filter((fruit) => !fruit.isDecayed);

불행히도 Typescript는 다음과 같이 말합니다.

형식에 호출 서명이없는 식을 호출 할 수 없습니다. Type '((callbackfn : (값 : Apple, 인덱스 : 숫자, 배열 : Apple []) => any, thisArg ?: any) => Apple []) | ... '에는 호환되는 호출 서명이 없습니다.

여기서 무엇이 잘못 되었습니까? Typescript가 신선한 과일을 좋아하지 않거나 Typescript 버그입니까?

공식 Typescript Repl 에서 직접 시도해 볼 수 있습니다 .


TypeScript는 구조적 타이핑 (덕 타이핑이라고도 함)을 지원합니다. 즉 , 동일한 멤버를 공유 할 때 유형이 호환됩니다 . 귀하의 문제가 있다는 것입니다 Apple그리고 Pear그들은 호환되지 않음을 의미 모든 회원을 공유하지 않습니다. 그러나 isDecayed: boolean멤버 만있는 다른 유형과 호환됩니다 . 때문에 구조 입력, 당신은 '상속 할 필요가 돈 ApplePear같은 인터페이스를.

이러한 호환 유형을 할당하는 방법에는 여러 가지가 있습니다.

변수 선언 중 유형 할당

이 문은 암시 적으로 다음과 같이 입력됩니다 Apple[] | Pear[].

const fruits = fruitBasket[key];

변수 선언에서 명시 적으로 호환 가능한 유형을 사용할 수 있습니다.

const fruits: { isDecayed: boolean }[] = fruitBasket[key];

추가 재사용을 위해 먼저 유형을 정의한 다음 선언에서 사용할 수도 있습니다 ( ApplePear인터페이스는 변경할 필요가 없습니다).

type Fruit = { isDecayed: boolean };
const fruits: Fruit[] = fruitBasket[key];

작업을 위해 호환되는 유형으로 캐스팅

주어진 솔루션의 문제점은 fruits변수 의 유형을 변경한다는 것 입니다. 이것은 당신이 원하는 것이 아닐 수도 있습니다. 이를 방지하려면 작업 전에 호환되는 유형으로 배열을 좁힌 다음 유형을 다음과 같은 유형으로 다시 설정할 수 있습니다 fruits.

const fruits: fruitBasket[key];
const freshFruits = (fruits as { isDecayed: boolean }[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

또는 재사용 가능한 Fruit유형 :

type Fruit = { isDecayed: boolean };
const fruits: fruitBasket[key];
const freshFruits = (fruits as Fruit[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

이 솔루션의 장점은 fruitsfreshFruits유형이 둘 다라 는 것입니다 Apple[] | Pear[].


FruitisDecayed를 제공 하는 공유 인터페이스를 만들 수 있습니다 . fruits이제 유형이 Fruit[]있으므로 유형이 명시적일 수 있습니다. 이렇게 :

interface Fruit {
    isDecayed: boolean;
}

interface Apple extends Fruit {
    color: string;
}

interface Pear extends Fruit {
    weight: number;
}

interface FruitBasket {
    apples: Apple[];
    pears: Pear[];
}


const fruitBasket: FruitBasket = { apples: [], pears: [] };
const key: keyof FruitBasket = Math.random() > 0.5 ? 'apples': 'pears'; 
const fruits: Fruit[] = fruitBasket[key];

const freshFruits = fruits.filter((fruit) => !fruit.isDecayed);

As mentioned in the github issue originally linked by @peter in the comments:

const freshFruits = (fruits as (Apple | Pear)[]).filter((fruit: (Apple | Pear)) => !fruit.isDecayed);

I had the same issue with numeral, a JS library. The fix was to install the typings again with this command:

npm install --save @types/numeral

참고URL : https://stackoverflow.com/questions/42427393/cannot-invoke-an-expression-whose-type-lacks-a-call-signature

반응형