I want to create a generic function to create actions in typescript-redux.
What I want is to use a function passing an interface as the type variable. So I'm starting with this function :
function action<F>(type: string, payload: any): F {
return { type, payload };
}
I want To use it like this :
interface Login {
type: LOGIN_REQUEST;
payload: credentials;
}
const Login = (credentials: Credentials)
=> action<Login>(LOGIN_REQUEST, credentials);
The problem is that is have this error :
Type '{ type: string; payload: any; }' is not assignable to type 'F'.
Since action
is generic there really is no way for the compiler to know that the object literal { type: string; payload: any; }
{ type: string; payload: any; }
{ type: string; payload: any; }
will satisfy the type F
. This code would also be a valid call:
action<{ type: string; payload: any; otherMandatoryProp: boolean }>(LOGIN_REQUEST, credentials);
F
in the above case has extra fields that action
will not fill.
The simplest solution is to break out of the type safety sandbox in this case and use a type assertion:
function action<F>(type: string, payload: any): F {
return { type, payload } as any;
}
This version would still allow a call with { type: string; payload: any; otherMandatoryProp: boolean }
{ type: string; payload: any; otherMandatoryProp: boolean }
{ type: string; payload: any; otherMandatoryProp: boolean }
which may cause some people to make some assumptions about what fields are on the retuned object. If you want to restrict F
to types with just type
and payload
you can use a type constraint that specifies that the properties type
and payload
exist on F
and if any other properties exist they are of type 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
The typescript return value should match the object that you are returning It Should be of type login( or you can set it to any)
function action<F>(type: string, payload: any): Login {
return { type, payload };
}
Because you won't return any value, but only Login
, you need to add a constraint:
function action<F extends Login>(type: string, payload: any): F {
return { type, payload } as F;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.