Typescript: определить тип полезной нагрузки и передать его обратному вызову - PullRequest
0 голосов
/ 25 февраля 2019

Вот упрощенный пример ввода моего магазина Redux.

interface SetNamePayload { name: string; }

export interface Action<TPayload extends object> {
    type: string;
    data: TPayload;
}

type SetNameAction = Action<SetNamePayload>;

// derive payload type from action type
type ResolveActionPayload<A extends Action<any>> =
    A extends Action<infer P> ? P : never;

// return type should be resolved to SetNamePayload
function getPayload<T extends SetNameAction>(x: T): ResolveActionPayload<T> 
{
    // TS2322: Type 'SetNamePayload' is not assignable to
    // type 'ResolveActionPayload<T>'.
    return x.data;
}

Почему тип возвращаемого значения не разрешен в SetNamePayload или возможно каким-либо другим способом определить тип полезной нагрузки действия, объявленный следующим образом?

Похоже, что обобщение наgetPayload как-то не так, потому что ResolveActionPayload работает, как и ожидалось:

enter image description here

Конечно, в реальном коде гораздо больше типов действий.Функция на самом деле больше похожа на getPayload<T extends SomeAction | OtherAction | ...>.Это действительно MWE проблемы.

Кроме того, я знаю, что могу изменить типизацию и использовать тип полезной нагрузки в качестве универсального параметра, например getPayload<T>(x: Action<T>): T, который, вероятно, будет работать намного проще и лучше.Тем не менее, этот тип типизации широко используется в кодовой базе, которая не полностью моя, и для нее потребуется много рефакторинга, которого я хочу попытаться избежать.

1 Ответ

0 голосов
/ 25 февраля 2019

Хотя условный тип, по-видимому, эквивалентен типу свойства data сценария типа действия, понять это невозможно.Условные типы обычно не раскрываются, если они содержат неразрешенные параметры типа.Хотя существует множество случаев, когда это имеет смысл сделать, эти случаи довольно специализированы и, как правило, не реализуются в компиляторе.

В этом случае было бы проще выразить тип как запрос типа.Это проще для компилятора выяснить, того же типа, что и x.data.Это работает

function getPayload<T extends SetNameAction>(x: T): SetNameAction['data'] 
{
    return x.data;
}

Playground link

...