如何为动态添加的方法定义方法签名?

时间:2019-04-29 21:08:40

标签: typescript

我的应用程序支持第三方插件。 我在我的应用程序中都有方法,我想将这些方法归类到单个“ API”类下,以便将其呈现给插件。

例如,我有一个Todo的{​​{1}}类。在运行时,我会自省Todo类,并将其所有方法添加到API类。所以我最终称呼

  

API ['deleteTodo'] = Todo ['deleteTodo']

我的插件现在可以愉快地调用deleteTodo(id)了,一切正常。

但是,tsc发出API.deleteTodo(id),我必须发出2339: Property 'deleteTodo' does not exist on type 'typeof API'。有没有一种简单的方法可以为//@TS-IGNORE定义方法签名以消除错误并为插件作者提供API方法的自动完成功能?

我尝试让API用定义的那些方法实现接口,但这没什么区别。添加界面...

  

类API实现Todo

...给出API.deleteTodo

如果我添加了部分...

  

2420: class 'API' incorrectly implements 'Todo'. Property deleteTodo is missing...

...我仍然得到class API implements Partial <Todo>

对于亚伦...

2339: property 'deleteTodo' does not exist...

2 个答案:

答案 0 :(得分:0)

您可能已经APIPartial实现了插件类,以允许方法成为undefined,直到您将它们附加:

class API implements Partial<Todo>, Partial<SomePlugin> {

}

不幸的是,在使用方法之前,您需要检查是否已附加方法:

if(api.deleteTodo) {
  api.deleteTodo(todo);
}

您还可以使用asAPI实例转换为API & Todo

const api = new API() as API & Todo;

如果编译器认为api.deleteTodo是一个函数,但在运行时它是undefined,则可能导致错误。

答案 1 :(得分:0)

这里发生了几件事...

function deleteTodo() { }
class API {}
API['deleteTodo'] = deleteTodo;
API.deleteTodo();  // This succeeds at runtime, but tsc gives 2339: Property 'deleteTodo' does not exist on type 'typeof API'

该示例分配静态类方法(API.deleteTodo())而不是实例方法(new API().deleteTodo())和interfaces cannot define static properties。但是,除非您实际上有一些实例方法或属性(即您在某处使用new API()),否则根本没有理由在这里使用类。

从示例中还不能完全清楚您是否具有预定的执行顺序。换句话说,您是否确保在任何地方使用API之前,API.deleteTodo()将拥有所有方法?如果是这样,那么我将分别定义API类型,并使用断言来避免在构建值的代码中编译错误:

// Define the API
interface API {
  deleteTodo(): void;
}

// Build the implementation
function deleteTodo() { }
const API: API = {} as API; // use `{} as API` to allow initializing an empty object
API["deleteTodo"] = deleteTodo; // fill in the API methods

// Now you can use it without any assertions
API.deleteTodo();

或者如果由于某些原因您确实需要使用类:

由OP编辑:这是我的用例的答案...

function deleteTodo() { }
interface API {
  deleteTodo(): void;
}
class BaseAPI {

}
BaseAPI["deleteTodo"] = deleteTodo;

type APIClass = { new(): BaseAPI } & API;

const API = BaseAPI as APIClass;

new API(); // No use for this in your examples, but if you have a use for it...
API.deleteTodo();

也:

  

在运行时,我会自省Todo类,并将其所有方法添加到API类中。

尚不清楚Todo类API是否提前知道。如果没有,那么以上将是不可能的。如果是这样的话,那么我不确定为什么为什么要静态地构建Todo类呢?

function deleteTodo() {}
function otherMethod() {}
function etc() {}

const API = {
  deleteTodo,
  otherMethod,
  etc
}

API.deleteTodo();
API.otherMethod();
API.etc()