我试图编写一个预期在给定接口中实现单个方法的类(具有不同的名称)。
在大多数情况下,这可以通过TypeScript泛型工作(请参阅下面的RpcHandler
)。
但是,因为TypeScript区分成员方法和成员属性,所以在将函数实现为方法而不是属性时会出现编译错误。
有没有办法提示打字稿RpcHandler#execute
应该是方法,而不是属性?
class Thing { }
interface RpcActions {
getThing(id: string): Promise<Thing>
}
// ---
class RpcHandler<ActionName extends keyof RpcActions> {
execute: RpcActions[ActionName];
}
// ---
class GetThingAsMethodHandler extends RpcHandler<'getThing'> {
// How can I declare the type of execute so that it is a member
// and not a property, so this doesn't error?
// Error: Class 'RpcHandler<"makeThing">' defines instance member
// property 'execute', but extended class 'MakeThingHandler' defines
// it as instance member function.
async execute(data: Object): Promise<Thing> {
return new Thing();
}
}
// Workaround, for now
class GetThingAsPropertyHandler extends RpcHandler<'getThing'> {
execute = async (id: string): Promise<Thing> => {
return new Thing();
}
}
答案 0 :(得分:1)
接口的方法和属性没有区别。它是为类维护的,可能是因为方法是在原型上定义的,如果初始化属性,则在构造函数中赋值 - 因此派生类原型中定义的可能方法对于在基类的构造函数。
因此,如果您可以将RpcHandler
转换为界面,它几乎可以正常工作,但execute
中的MakeThingHandler
不能接受任何参数:
class Thing { }
interface RpcActions {
makeThing(): Promise<Thing>
getThing(id: string): Promise<Thing>
}
// ---
interface RpcHandler<ActionName extends keyof RpcActions> {
execute: RpcActions[ActionName];
}
// ---
class MakeThingHandler implements RpcHandler<'makeThing'> {
async execute(): Promise<Thing> {
return new Thing();
}
}
使用您的代码,当execute
有data: Object
参数时,您将获得
test.ts(17,7): error TS2420: Class 'MakeThingHandler' incorrectly implements interface 'RpcHandler<"makeThing">'.
Types of property 'execute' are incompatible.
Type '(data: number) => Promise<Thing>' is not assignable to type '() => Promise<Thing>'.
可能的解决方法是将RpcActions中的makeThing()声明为
makeThing(arg: any): Promise<Thing>