Typescript:推断有效载荷类型并将其传递给回调

时间:2019-02-25 12:14:01

标签: typescript typescript-generics

这是键入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 :(得分:0)

虽然条件类型似乎等同于动作类型脚本的data属性的类型,但无法弄清楚。如果条件类型包含未解析的类型参数,则通常不会扩展它们。尽管在很多情况下,这样做是有意义的,但这些情况非常专业,通常不会在编译器中实现。

在这种情况下,将类型表示为类型查询会更容易。对于编译器来说,这很容易找出与x.data相同的类型。可行

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

Playground link