const foo = (a: string, b: string) => {
console.info('foo', a, b);
};
const bar = (a: number, b: number) => {
console.info('bar', a, b);
};
const factory =
<M extends typeof foo | typeof bar>(method: M) =>
(...args: Parameters<M>) => {
method(...args);
};
Я хочу создать фабрику нескольких функций (имеет разные аргументы)
Но TypeScript выдает ошибку ниже сообщения.
A spread argument must either have a tuple type or be passed to a rest parameter.
Возвращает ли Parameters кортеж типа утилиты?
Это ограничение конструкции, описанное в ms/TS#47615 . Рекомендуемый подход — сделать рефакторинг общим для списка параметров, а не для типа функции, как показано в этой ссылке на игровую площадку. Это полностью решает вопрос? Если да, то я напишу ответ с объяснением; если нет, то что мне не хватает?
@jcalz Это работает идеально! Спасибо :D






TypeScript не очень хорошо понимает общие условные типы ; в частности, он не всегда может просмотреть тип утилиты «Параметры<M>» для универсального типа функции M и понять, что выходные данные всегда можно расширять. Это считается ограничением дизайна TypeScript, как описано в microsoft/TypeScript#47615.
В соответствии с этой проблемой рекомендуемый подход — сделать функцию универсальной в списке аргументов A и возвращаемом типе R типа функции отдельно. Для вашего кода тип возвращаемого значения всегда void, поэтому мы можем сделать его просто универсальным в A:
const factory = <A extends Parameters<typeof foo | typeof bar>>(
method: (...args: A) => void) => (...args: A) => {
method(...args);
};
Поскольку известно, что тип A из args является типом остальных параметров для method, вызов разрешен. И хотя для примера это не обязательно важно, A было ограничено до Parameters<typeof foo | typeof bar>, чтобы вы не могли передавать случайные функции в:
factory(foo)("a", "b"); // okay
factory(bar)(1, 2); // okay
factory((a: string, b: number) => { }) // error!
Мне кажется, это ошибка TypeScript. Это работает, если вручную сделать функцию
M extends (...args: Parameters<typeof foo | typeof bar>) => (ReturnType<typeof foo | typeof bar>).