Closed pachuka closed 6 years ago
I would suggest to create a question on stack overflow, you can link it here for reference.
I have simillar trouble. Making generic method to deal witch async action (for making api calls in thunks, sagas or epics) could reduce lots of repetetive code.
@abdurahmanus check SO question I have provided some quick answer there, hope that helps.
@piotrwitek - nice! I have been using something similar, but this is much cleaner now.
Glad you like it 🙂 I also have plans to improve all the remaining Creator types to better handle generic scenarios in consumer code
Thank you for quick response! This is exactly what I was looking for.
One more issue however.
const aa = createAsyncAction("request", "success", "failure")<
number,
{ foo: "bar" },
string
>();
function* asyncSaga<
TRequestType extends string,
TRequestPayload,
TSuccessType extends string,
TSuccessPayload,
TFailureType extends string,
TFailurePayload
>(
asyncAction: AsyncActionCreator<
[TRequestType, TRequestPayload],
[TSuccessType, TSuccessPayload],
[TFailureType, TFailurePayload]
>
) {
// not implemented
yield;
};
function* someSaga() {
yield call(asyncSaga, aa);
}
Sorry but this is not typesafe-actions related, it's obviously an issue with the call type.
If you can solve this issue I'm willing to add it in the recipes section as it can be really useful for other ppl.
One workaround for this case is to explicitly specify call type. Something like this. Looks not very ellegant thow.
const aa = createAsyncAction("request", "success", "failure")<
number,
{ foo: "bar" },
string
>();
const aa2 = createAsyncAction("request1", "success", "failure")<
boolean,
{ foo: "bar" },
string
>();
function* asyncSaga<
TRequestType extends string,
TRequestPayload,
TSuccessType extends string,
TSuccessPayload,
TFailureType extends string,
TFailurePayload
>(
asyncAction: AsyncActionCreator<
[TRequestType, TRequestPayload],
[TSuccessType, TSuccessPayload],
[TFailureType, TFailurePayload]
>,
requestPayload: TRequestPayload
): IterableIterator<any> {
// not implemented
}
type Actions<AC> = AC extends AsyncActionCreator<infer RA, infer SA, infer FA>
? { request: RA; success: SA; failure: FA }
: never;
type AsyncSaga<AC extends AsyncActionCreator<any, any, any>> = {
(a: AC, rp: Actions<AC>["request"][1]): any;
};
function* someSaga() {
asyncSaga(aa, 1);
yield call<AsyncSaga<typeof aa>>(asyncSaga, aa, 2); // correct actions and request payload
// yield call<AsyncSaga<typeof aa>>(asyncSaga, aa); // not all arguments provided
// yield call<AsyncSaga<typeof aa>>(asyncSaga, aa, "2"); // wrong request payload type
// yield call<AsyncSaga<typeof aa>>(asyncSaga, aa2, 2); // wrong action
}
Isn't it the problem with the return type of asyncSaga that call is not inferring correctly?
What is the type declaration for call
I think no. As you can see from screenshots above. Type "string" is not assignable to type "request" and so on
What you say is actually a symptom, not a cause. The error shows that the inference in the call
function didn't work at all falling back to default types.
Hi Piotrwitek,
I'm having some trouble wrapping my head around how to pass an AsyncAction created via CreateAsyncAction while keeping the typing information, for example in my case I am trying to create a generic GraphQL query epic using ApolloClient since all of those will have the same REQUEST/SUCCESS?FAILURE flow:
What type should the asyncAction be so that the isActionOf and the action.Payload resolve properly?
Thanks!