如何将类型参数的方法添加到使用代理

时间:2016-10-18 10:49:49

标签: typescript ecmascript-6 es6-proxy

我正在开发一个简单的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...

我试图浏览一些类似的工作类型,但找不到办法。谢谢你的帮助。

1 个答案:

答案 0 :(得分: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

code in playground

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

修改

如果我理解,那么您需要做的就是告诉编译器您的实例属于Api类型:

class ServiceClient {
    // implement proxy magic here
}

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

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