Búsqueda de sitios web

javascript - ¿Cómo usar Proxy<T> con un tipo diferente a T como argumento?


Estoy en una situación en la que quiero usar Proxy para "balancear la carga" entre una lista de clases.

Un ejemplo ingenuo de lo que estoy intentando hacer es el siguiente:

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();

Esto "funciona". El problema es que estoy usando TypeScript. Y, debido a la definición de tipo Proxy, no podemos hacer algo como

new Proxy<Foo>([new Foo(), new Foo()], handler)

ya que produce el siguiente error:

El argumento de tipo 'Foo[]' no es asignable al parámetro de tipo 'Foo'.

¿Hay una manera de lograr esto; sin perder la verificación de tipos?

Respuesta #1

No necesitas cambiar las definiciones existentes, solo puedes aumentarlas.

Si estás utilizando un sistema de módulos, necesitas redeclarar el ProxyConstructor en global para que funcione:

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();

Respuesta #2

Una solución sencilla es crear una fábrica como esta:

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();

De esa manera tienes un equilibrador reutilizable y seguro en tipos sin comprometer ninguna declaración.

Artículos relacionados