7

I have 2 Actions and an Effect for these 2 actions using ofType operator as below:

export const myActions = {
  actionA: createAction(`actionA`, props<{ a: string }>()),
  actionB: createAction(`actionB`, props<{ b: number }>())
}

myEffect$ = createEffect(() =>
  this.actions$.pipe(
    ofType(myActions.actionA, myActions.actionB),
    mergeMap(action => {
      // How to convert action object to correct type and access action.a or action.b props?
      if (action.type == myActions.actionA) {
        console.log(action.a); // compile error
      } else if (action.type == myActions.actionB) {
        console.log(action.b); // compile error
      }
    })
  ), {dispatch: false}
);

How can I check and access props of actions (action.a and action.b) and with auto-completion from IDE?

Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
Xuan
  • 578
  • 6
  • 14
  • 1
    Why not just create 2 effects? – timdeschryver Feb 23 '20 at 11:37
  • what about redux dev tools? https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en – Przemyslaw Jan Beigert Feb 25 '20 at 10:13
  • @timdeschryver Why not just create 2 effects? => I need the value from actionA and actionB for the same logic after that. In the example, I simplified to 2 actions. But I need actually 5 actions with the same logic and don't want to create 5 effects. – Xuan Feb 25 '20 at 11:18
  • @PrzemyslawJanBeigert I use console.log just for example. In real life, I use for other purposes. – Xuan Feb 25 '20 at 11:19
  • @XuanDaiNguyen please **include** some of the logic which requires sharing - if the props are of different types you'd have deal with this regardless of the fact this is in an effect similar to overloading a method – Andrew Allen Feb 25 '20 at 12:01
  • @AndrewAllen This question is about coding technique regardless of logic. And it is answered by PrzemyslawJanBeigert. – Xuan Feb 25 '20 at 20:34
  • 1
    @XuanDaiNguyen than the answer is *it depends* but that you should have a good reason for not using 2 effects. Potential alternative 3 effects, 2 mapping to a common action with same props type, 1 effect implements common action. Unable to explore without concrete idea – Andrew Allen Feb 25 '20 at 23:37
  • @AndrewAllen I already answered the question "Why not just create 2 effects?" from timdeschryver in the comment above, please check again. – Xuan Feb 26 '20 at 22:43

1 Answers1

11

ofType takes as generic params type of action e.g. ofType<Action>(actionType) then merge map argument will be typed as Action without typing.

In your case action argument can be ActionA or ActionB as well, so you have to write ofType<ActionA | ActionB>(actionTypeA, actionTypeB), then action from mergeMap will be typed as Union of ActionA and ActionB. But in proper if's branches like (action.type == myActions.actionA) action will be only ActionA typed, because TS complier understand some of ifs statement.

BTW advice of @timdeschryver to split it into 2 effects is very good.

==============edited=================

If you're defining action by export const actionA = createAction('actionA', props<{ a: string }>()) you can declare type of ActionA by type ActionA = ReturnType<typeof actionA>;. ReturnType is generic added to TypeScript.

Przemyslaw Jan Beigert
  • 2,351
  • 3
  • 14
  • 19