0

我正在为我的内部使用开发一个简单的 RPC 客户端/服务器库。我想使用一个接口来描述客户端和服务器,这样我就可以在我的通用应用程序中的服务器和浏览器之间共享它们。

服务器很简单,服务只是扩展了我的 Service 类并实现了一个描述 API 的接口。

客户端将实现为 ES6 代理,只需将所有方法调用发送到服务器,我希望它具有强类型以及服务类。我需要 ServiceClient 类型的实例来拥有它的类型参数的所有方法和属性,不管它是什么。

我在考虑这种语法:

interface Api
{
    foo(): boolean;
}

class MyService extends Service implements Api
{
    public foo(): boolean { return true; }
}

// usage
let result = (new ServiceClient<Api>()).foo(); // type of result is inferred, I get an error if I try to use an undefined method, arguments are type checked...

我试图浏览一些类似的类型,但找不到方法。谢谢您的帮助。

4

1 回答 1

1

我希望我明白你在问什么。

您不能T在运行时使用泛型参数 (),因此您不能动态创建代理对象来实现T.

你可以做的是这样的:

interface Api {
    foo(): boolean;
}

abstract class Service {}

class MyService extends Service implements Api {
    public foo(): boolean { return true; }
}

const myService = new MyService();
const ServiceClient = {} as Api;
for (let key in myService) {
    if (typeof myService[key] === "function" && key !== "constructor") {
        ServiceClient[key] = function() {
            return myService[key].apply(myService, arguments);
        }
    }
}

let result = ServiceClient.foo(); // true

操场上的代码

我所做的是创建了一个实例MyService,然后我创建了一个对象,它将作为 this 的代理myService,这个代理ServiceClient首先创建为一个空对象。
然后我遍历MyService实例的属性,并为每个函数(不是构造函数)在代理对象上创建一个具有相同名称的函数,当每个函数被调用时,等效函数 inmyService被调用。


编辑

如果我理解,那么您需要做的就是告诉编译器您的实例是 type Api

class ServiceClient {
    // implement proxy magic here
}

let client = new ServiceClient() as any as Api;
let result = client.foo();

这应该可以解决问题,因为它创建了一个代理事物的类的实例,然后诱使编译器认为这是Api.

于 2016-10-18T11:27:43.080 回答