如何将模板化类类型声明为成员方法,*不是*属性?

时间:2016-12-29 03:20:53

标签: typescript

我试图编写一个预期在给定接口中实现单个方法的类(具有不同的名称)。

在大多数情况下,这可以通过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();
  }
}

1 个答案:

答案 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();
  }
}

使用您的代码,当executedata: 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>