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

Typescript:推断有效负载类型并将其传递给回调,typescript,typescript-generics,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

下面是一个输入我的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{name:string;}
导出接口操作{
类型:字符串;
资料:TPayload;
}
类型SetNameAction=Action;
//从操作类型派生有效负载类型
类型解析操作负载

当然,在实际代码中还有更多的动作类型。该函数实际上看起来更像
getPayload
。这确实是一个问题的关键


另外,我知道我可以反转键入并使用payload type作为泛型参数,比如
getPayload(x:Action):T
,这可能会更简单、更好。然而,这种类型在代码库中被广泛使用,而代码库并不全是我的,它需要进行大量重构,我希望尽量避免这种重构。

而条件类型似乎与action typescript的
data
属性的类型等价,但我无法理解这一点。如果条件类型包含未解析的类型参数,则它们通常不会展开。虽然有很多情况下这样做是有意义的,但这些情况非常特殊,通常不在编译器中实现

在这种情况下,将类型表示为类型查询会更容易。对于编译器来说,这更容易确定是与
x.data
相同的类型。这很有效

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