我处在一种情况,我想使用Proxy
来在类列表之间“加载平衡”。
我正在尝试做的一个简单的例子如下:
class Foo {
constructor(private msg: string) {}
foo() {
console.log(this.msg);
}
}
// @ts-ignore
const proxy: Foo = new Proxy([new Foo('foo'), new Foo('bar')], {
get: (o, key) => {
const client = o[Math.floor(Math.random() * o.length)];
console.log(client, key);
return client[key];
},
});
proxy.foo();
这“有效”。问题是我正在使用打字稿。而且,由于Proxy
类型定义,我们无法执行类似
new Proxy<Foo>([new Foo(), new Foo()], handler)
因为它产生以下错误:
'Foo []'类型的参数不能分配给'Foo'类型的参数。
有没有办法实现这一目标;没有丢失类型检查?
答案 0 :(得分:3)
您不需要更改现有定义,只需对其进行扩充即可。
如果您使用的是模块系统,则需要重新声明全局ProxyConstructor
才能使其正常工作:
declare global {
interface ProxyConstructor {
new <TSource extends object, TTarget extends object>(target: TSource, handler: ProxyHandler<TSource>): TTarget;
}
}
const proxy: Foo = new Proxy<Foo[], Foo>([new Foo('foo'), new Foo('bar')], {
get: (o, key) => {
const client = o[Math.floor(Math.random() * o.length)];
console.log(client, key);
return client[key];
},
});
proxy.foo();
答案 1 :(得分:1)
您可以编辑Proxy
类型定义,以允许与其参数类型不同的类型。
interface ProxyConstructor {
revocable<T extends object, S extends object>(
target: T,
handler: ProxyHandler<S>,
): { proxy: T; revoke: () => void };
new <T extends object>(target: T, handler: ProxyHandler<T>): T;
new <T extends object, S extends object>(target: S, handler: ProxyHandler<S>): T;
}
declare var Proxy: ProxyConstructor;
然后将Proxy
用法修改为以下内容:
const proxy: Foo = new Proxy<Foo, Foo[]>([new Foo('foo'), new Foo('bar')], {
get: (o, key) => {
const client = o[Math.floor(Math.random() * o.length)];
console.log(client, key);
return client[key];
},
});
答案 2 :(得分:0)
一个简单的解决方案是创建一个这样的工厂:
function balance<T>(instances: Array<T>): T {
return new Proxy<any>({}, {
get: (o, key) => {
const client = instances[Math.floor(Math.random() * instances.length)];
console.log(client, key);
return client[key];
},
}) as T;
}
const proxy = balance([new Foo('foo'), new Foo('bar')]);
proxy.foo();
通过这种方式,您可以使用可重复使用且类型安全的平衡器而不会泄露任何声明。