我在使用适配器时收到类型错误,如此缩减示例中所示(请参阅方法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)
),但在我的情况下,接口会非常大。
思考?我是否坚持为适配器创建一个巨大的通用接口?
答案 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)
。