无法调用类型缺少调用签名的表达式

时间:2016-10-10 18:02:56

标签: typescript typescript2.0

我在使用适配器时收到类型错误,如此缩减示例中所示(请参阅方法getGloryOfAnimal的最后一行)。我感到困惑,因为据我所知,这些类型是完全明确的。

interface ICheetah {
    pace: string;
}

interface ILion {
    mane: string;
}

let LionAdapter = {
    endpoint: 'lion',
    castRawData: (d: any) => d as ILion,
    getValue: (d: ILion) => d.mane
}

let CheetahAdapter = {
    endpoint: 'cheetah',
    castRawData: (d: any) => d as ICheetah,
    getValue: (d: ICheetah) => d.pace
}

type AnimalAdapter = typeof CheetahAdapter | typeof LionAdapter;

function getDataFromEndpoint(endpoint: string): any {
    // data comes back in a format from the server
    // synchronous here for simplicity
    if (endpoint === 'cheetah') {
        return {
            pace: 'lightning speed'
        };
    } else {
        return {
            mane: 'shiny mane'
        };
    }
}

function getGloryOfAnimal(adapter: AnimalAdapter): string {
    let data = adapter.castRawData(getDataFromEndpoint(adapter.endpoint));
    // type error below:
    // 'cannot invoke expression whose type lacks a call signature'
    return adapter.getValue(data); 
}

console.log(getGloryOfAnimal(LionAdapter));

我相信我可以为两个适配器编写一个接口,而不是创建一个联合类型(例如(T | U)),但在我的情况下,接口会非常大。

思考?我是否坚持为适配器创建一个巨大的通用接口?

1 个答案:

答案 0 :(得分:0)

此错误的原因是adapter.getValue的类型为:

((d: ICheetah) => string) | ((d: ILion) => string)

这种类型确实没有呼叫签名。

data的类型是:

ICheetah | ILion

如果adapter.getValue的类型为:

,那会有所帮助
(d: ICheetah | ILion) => string

我的问题是你为什么不上课?然后实际的函数将是已知类型的类方法。

修改

您可以通过执行以下操作来解决此错误:

let LionAdapter = {
    endpoint: 'lion',
    getValue: (d: any) => d.mane
}

let CheetahAdapter = {
    endpoint: 'cheetah',
    getValue: (d: any) => d.pace
}

function getGloryOfAnimal(adapter: AnimalAdapter): string {
    return adapter.getValue(getDataFromEndpoint(adapter.endpoint)); 
}

这也消除了castRawData的需要 如果您仍想要类型安全,请将d替换为(d as ICheetah)