Динамичная типизация параметров функции
Описание
Есть некий класс MachineState<T> и T это тип, который он "принимает". Я создаю функцию, которая "поддает" сразу несколько данных, нескольким MachineState-ам:
await context.runFunctionsParallel(sign(5), [
[this.#stateBettingOnSport, { id: 3 }], /// [MachineState<A>, A]
[this.#stateBettingOnCasino, { code: "cb12" }], /// [MachineState<B>, B]
]);
Собственно, создаю эту функцию:
async runFunctionsParallel<T extends readonly [MachineState<object>, object][]>(signature: SignatureGenerator, values: {
-readonly [K in keyof T]:
T[K] extends [MachineState<infer P>, infer V]
? P extends V
? V extends P
? [MachineState<P>, P]
: never
: never
: never;
}): Promise<unknown[]> {
...
}
Проблема
Функция не выдает ошибок, но и не работает. Я не получаю типовые подсказки и проверки.
Вопрос
Где моя ошибка?
Дополнение 1
Пример описания функции, которое работает, без массива:
async runFunction<T extends {}>(signature: SignatureFunction, state: MachineState<T>, data: T): Promise<unknown> {
...
}
Ответы (1 шт):
Вкратце, что неправильно прямо сейчас:
При вызове функции TS не знает, за что зацепиться для определения
T. В типе параметраvaluesэтот самыйTдолжен быть "напрямую":values: T & {...}. Но такой способ может допускать лишние ключи, и не факт что будет нормально подсказывать существующие.Если сделать по способу из п.1, T выводится как массив. А надо кортеж, иначе может пропускать несоответствия типов.
Дополнение к ответу
Поэкспериментировал в плейграунде, вышло так.
П.1 решается за счет трюка с тернарником: values: T extends unknown ? Pairs<T> : T. Здесь, с одной стороны, формально T может быть типом для values, и TS выставляет в него тип переданного объекта. С другой стороны, по факту условие всегда истинно, и мы идем в Pairs, где на основе T формируем желаемый тип, по которому и делается проверка для переданного значения. Круг замкнулся, в общем.
П.2 разруливается странным ограничением для T, с участием кортежа: T extends [Item, ...Item[]] | Item[]. Без этого T выводился как массив, даже вышеупомянутый const не помогал. Тут без комментариев.