1. ホーム
  2. javascript

型に呼び出し署名がない式を呼び出すことができない

2023-08-29 23:06:10

質問

私はリンゴと梨を持っていますが、どちらにも isDecayed 属性があります。

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

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

そして、どちらのタイプも私のフルーツバスケットに(複数回)入れることができます。

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

とりあえずバスケットが空だとします。

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

ここで、カゴからランダムに1種類を取り出します。

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

そしてもちろん、腐った果物は誰も好きではありませんから、新鮮なものだけを選びます。

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

残念ながらTypescriptが教えてくれました。

呼び出しシグネチャを持たない型を持つ式は呼び出すことができません。型 '((callbackfn: (value: Apple, index: number, array: Apple[]) => any, thisArg?: any) => Apple[]). | ...'は互換性のあるコールサインを持ちません。

Typescriptが新鮮な果物を好まないだけなのか、それともTypescriptのバグなのでしょうか?

自分で試すことができるのは、公式の Typescript Repl .

どのように解決するのですか?

TypeScriptは構造的な型付け(ダック型付けとも呼ばれる)をサポートしており、つまり 型が同じメンバを共有している場合、互換性があります。 . あなたの問題点は ApplePear はすべてのメンバーを共有していないため、互換性がありません。しかし、この型は 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[] .