typesafe-actions
typesafe-actions copied to clipboard
make isActionOf accept an AsyncAction
Is your feature request related to a problem?
I would like to know if an action is coming from an action creator created using createAsyncAction, in an elegant and typesafe way.
Describe a solution you'd like
I would like to have isActionOf accept an object created by createAsyncAction. Or maybe have a isAsyncActionOf.
Describe alternatives you've considered
For now I have to type the three possible action creators in an array provided to isActionOf
const fetchTodos = createAsyncAction(
'todos/fetch_request',
'todos/fetch_success',
'todos/fetch_failure'
)< void, Todo[], CustomError >();
const todoAsyncActions = [ fetchTodos.request, fetchTodos.failure, fetchTodos.success ];
let requestName;
if (isActionOf(todoAsyncActions , action)) {
requestName = 'todos';
}
Here is something I did try (but cannot provide type safety of the payload)
export type SimpleAsyncAction = { getType: () => string };
export type AsyncActionStates = 'request' | 'failure' | 'success';
export type SimpleAsyncActions = {
[k in AsyncActionStates]: SimpleAsyncAction
};
export const isFromAsyncAction = (asyncActions: SimpleAsyncActions) => (
action: FluxStandardAction,
) =>
Object.values(asyncActions).some(
(asyncAction) => asyncAction.getType() === action.type,
);
I have a plan for this feature.
At the moment isActionOf has really complex overloads and it would introduce too much complexity if we would want to add type inference logic there to handle async actions as well.
Separate utility is also not optimal as I don't want to create special API for any particular creator type, I would rather prefer more generic utility.
I think the best solution would be to refactor isActionOf to use tuples, that would simplify overloads and would allow to extend isActionOf to handle async actions as well.
const fetchTodos = createAsyncAction(
'todos/fetch_request',
'todos/fetch_success',
'todos/fetch_failure'
)< void, Todo[], CustomError >();
if (isActionOf(fetchTodos, action)) {
action; // requestAction | successAction | errorAction
}
Question maybe related to this, is it possible to create an ActionType that only contains the AsyncActions?
Ex: Today we do
export type RootAction = ActionType<typeof rootAction>;
which contains all actions regardless of async action or not.
could we have
export type AsyncAction = AsyncActionType<typeof rootAction>;
which returns typings for only the Async ones?
@pachuka I haven't try but I guess yes, create a feature request and me or someone else might pick it up. It would need to add tag property to the async-action-creator and it should work like a charm.
@issuehunt has funded $100.00 to this issue.
- Submit pull request via IssueHunt to receive this reward.
- Want to contribute? Chip in to this issue via IssueHunt.
- Checkout the IssueHunt Issue Explorer to see more funded issues.
- Need help from developers? Add your repository on IssueHunt to raise funds.
hi @piotrwitek, I'd like to work on this issue, is this still relevant? I mean, if no one else have started work on this?
Hey @kononenko-a-m, I've been working on it and have made some progress, although I hit the blocker because of design limitations, and I wanted to rethink the design but I don't remember all the details now. Are you familiar with the async action implementation and tried to implement it? It won't be easy.
@piotrwitek In general, yes.
so you want to have mentioned by you behaviour work:
const fetchTodos = createAsyncAction(
'todos/fetch_request',
'todos/fetch_success',
'todos/fetch_failure'
)< void, Todo[], CustomError >();
if (isActionOf(fetchTodos, action)) {
action; // requestAction | successAction | errorAction
}
right?
the simplest solution which I see for this would be defining several overloading for isActionOf, like this:
export function isActionOf<
TType1 extends TypeConstant,
TPayload1 extends any,
TArgs1 extends any[],
TType2 extends TypeConstant,
TPayload2 extends any,
TArgs2 extends any[],
TType3 extends TypeConstant,
TPayload3 extends any,
TArgs3 extends any[]
>(asyncAction:
ReturnType<
AsyncAction<
TType1, unknown, unknown, TArgs1,
TType2, unknown, unknown, TArgs2,
TType3, unknown, unknown, TArgs3,
never, unknown, unknown, never
>
>,
action: { type: string }): action is
| PayloadAction<TType1, TPayload1>
| PayloadAction<TType2, TPayload2>
| PayloadAction<TType3, TPayload3>
this gives desired result, but it wouldn't be very elegant. not sure if it's ok for you?
Hey! Is this issue still up for grabs(Issuehunt bouny)? Thanks! @piotrwitek @kononenko-a-m