Search code examples
typescriptreduxswitch-statementtypescript-typingsredux-reducers

How to implement an exhaustive switch statement inside a Redux reducer function using Typescript? How to handle Redux's internal @@redux actions


I've tried to find a definitive answer do this, but haven't found one yet.

There a question here on SO that answers how to implement an exhaustive switch statement:

How do I check that a switch block is exhaustive in TypeScript?

And the answer is:

Write a function that takes never as a parameter, returns never and will throw when called with anything.

function assertUnreachable(x: never): never {
  throw new Error("Didn't expect to get here");
}

And use it in your default case:

switch (action.type) {
  case "A": {
    ...
  }
  case "B": {
    ...
  }
  default: {
    return assertUnreachable(action);  // CAN'T USE action.type HERE BECAUSE action WILL BE never AND action.type WILL BE any
  }
}

But I can't use it like this inside a reducer. It will work as far as checking exhaustiveness for my reducer actions, but will throw during runtime because Redux will call it with its own internal actions, like, for example:

@@redux/INITh.b.0.x.q.h                   // THIS IS THE action.type
@@redux/PROBE_UNKNOWN_ACTIONe.7.b.o.p     // THIS IS THE action.type

So what is the ideal way of handling exhaustiveness of a switch statement inside a reducer?


Solution

  • The right answer here is to not worry about this at all.

    Even with that switch statement, your reducer will be called with other actions. So, trying to limit the exact set of actions doesn't really help.

    The better approach is to use the createSlice API from our official Redux Toolkit package, and let it define what actions you expect to handle in that particular slice.