Если ваш существующий GenericActionCreator<T>
подходит для ваших сценариев использования, он мне подходит.
Есть, конечно, разные способы получить поведение, о котором вы говорите ... но я не понимаю Не знаю, что кто-то из них более «элегантный» (или, по крайней мере, это вопрос мнения). Вот версия, которая дает те же типы вывода, что и у вас (обратите внимание, что имена параметров функции не считаются частью типа ... поэтому (x: string)=>void
и (y: string)=>void
- это один и тот же тип), но выражает это по-разному:
type GenericActionCreator<T extends GenericAction<string, unknown>, P = T["payload"]> =
(...p: undefined extends P ? [P?] : [P]) => T
Я объясню каждое изменение и отмечу, что каждое изменение может применяться или не применяться независимо от других, поэтому вы можете отказаться от любого изменения, которое вам не нравится:
- У меня есть заменил
TAction
на T
. Это только косметическое изменение c. T extends GenericAction<string, T["payload"]>
является рекурсивным, но не обязательным; вместо этого вы можете заменить его на T extends GenericAction<string, unknown>
, потому что любой T
, назначаемый на GenericAction<string, unknown>
, по необходимости будет назначаться на GenericAction<string, T["payload"]>
- Поиск
T["payload"]
выполняется в вашей версии несколько раз; Есть разные способы избежать повторения этого поиска. Один из них - присвоить его новой переменной типа c generi P
, значением по умолчанию которой является желаемое значение; это то, что я сделал с type GAC<T, P = T["payload"]> = ⋯
. Другой способ - использовать условный вывод типа: type GAC<T> = T["payload"] extends infer P ? ⋯: never
. - Поскольку обе ветви вашего условного типа выглядят как
(⋯) => T
, может быть возможно поместить условный тип в список параметров функции, чтобы избежать дублирования сигнатуры функции. Существует связь между списками параметров и кортежами , которую мы можем использовать для этого: Тип функции (x: X)=>void
также может быть записан (...xs: [X])=>void
; первый является функцией одного аргумента типа X
, а второй - функцией, чей список аргументов представляет собой одноэлементный кортеж типа X
. И тип функции (x?: X)=>void
также может быть записан (...xs: [X?])=>void
; первый является функцией одного необязательного аргумента типа X
, а второй - функцией, список аргументов которой представляет собой одноэлементный необязательный кортеж типа X
. Этот знак вопроса после типа в кортеже обозначает его как необязательный ... вы можете думать о [X?]
как об объединении [] | [X]
.
Хорошо, надеюсь, это поможет вам дать некоторые варианты и направление. Удачи!
Детская площадка ссылка на код