Как использовать Proxy <T>с типом, отличным от T, в качестве аргумента? - PullRequest
0 голосов
/ 30 мая 2018

Я нахожусь в ситуации, когда я хочу использовать 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'.

Есть ли способ добиться этого;без потери проверки типов?

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Вам не нужно изменять существующие определения, вы можете просто дополнить их.

Если вы используете модульную систему, вам нужно переопределить глобальный 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();
0 голосов
/ 30 мая 2018

Простое решение состоит в том, чтобы создать фабрику, подобную этой:

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

Таким образом, вы получаете многоразовый и надежный балансировщик без ущерба для любой декларации.

0 голосов
/ 30 мая 2018

Вы можете отредактировать определение типа 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];
    },
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...