打字稿不能转换为泛型类型变量

C T*_*que 3 typescript redux

我想创建一个通用函数来在 typescript-redux 中创建操作。

我想要的是使用传递接口作为类型变量的函数。所以我从这个功能开始:

function action<F>(type: string, payload: any): F {
    return { type, payload };
}
Run Code Online (Sandbox Code Playgroud)

我想像这样使用它:

interface Login {
    type: LOGIN_REQUEST;
    payload: credentials;
}

const Login = (credentials: Credentials) 
     => action<Login>(LOGIN_REQUEST, credentials);
Run Code Online (Sandbox Code Playgroud)

问题是有这个错误:

Type '{ type: string; payload: any; }' is not assignable to type 'F'.
Run Code Online (Sandbox Code Playgroud)

Tit*_*mir 7

由于action是泛型,编译器确实无法知道对象文字{ type: string; payload: any; }是否满足 type F。此代码也将是一个有效的调用:

action<{ type: string; payload: any; otherMandatoryProp: boolean }>(LOGIN_REQUEST, credentials);
Run Code Online (Sandbox Code Playgroud)

F在上述情况下有额外的字段action不会填写。

在这种情况下,最简单的解决方案是跳出类型安全沙箱并使用类型断言:

function action<F>(type: string, payload: any): F {
    return { type, payload } as any;
}
Run Code Online (Sandbox Code Playgroud)

这个版本仍然允许调用,{ type: string; payload: any; otherMandatoryProp: boolean }这可能会导致一些人对重新调整的对象上的字段做出一些假设。如果你想限制F到类型的只是typepayload你可以使用一个类型约束,它指定的属性typepayload存在于F和是否存在任何其他属性他们是类型never

function action<F extends { type : string, payload : any} & { [P in Exclude<keyof F, 'type' | 'payload'>]: never }>(type: string, payload: any): F {
    return { type, payload } as any;
}
const Login = (credentials: credentials) => action<Login>(LOGIN_REQUEST, credentials);
action<{ type: string; payload: any; otherMandatoryProp: boolean }>(LOGIN_REQUEST, {}) // invalid call
Run Code Online (Sandbox Code Playgroud)