Extracting useful types from a mapped action creator
The context: typescript, redux, react.
You may or may not know that if you dispatch a thunk (those action creators that return a function that is then processed by the redux-thunk middleware), you can actually await the dispatch and the return value from the dispatched thunk will also be returned…
In this example, updateSomething is an action creator producing a thunk. We then had the situation that we were interested in the return value of said thunk (A simple boolean that states whether the update was successful or not). However, such an async action creator looks something like that:
When this is mangled through the connect
from react-redux, we can call the function and can await the return value of the thunk. That is, in Typescript terms this amounts to a function of the signature (id: string) => Promise<boolean>
. Alas, the original async action creator has the signature
Ouf, this is definitely not the return value we want to await!
What can we do?
Let’s create some helper Typescript that will extract the type
from
Let’s define the ThunkAction, it is the signature of the function that is returned from an async action creator, alongside the type definition(s) of such async action creators:
Here, we just cater for async action creators that may accept more than one argument. A max of three ought to be enough 😁.
Next, we define a type that describes a function - its type argument is itself a function, namely an async action creator.
First we tell the linter to shut up about the function type - it is a good type constraint for the thing we want to check. Then we define a conditional type - this caters for the different type definitions related to the differing number of input arguments. Then, for each case we want to consider we produce the desired type definition, e.g.
Based on this type definition we can create a utility function that will do the type conversion for us:
You may think that that any
looks a bit dodgy but the correct function definition is passed to the type that is handling what type to produce from the input.
This means that if the passed function cannot be mapped to any of the known signatures of an AsyncActionCreator, the compiler will complain…
Now you can use the utility function in the example shown in the beginning to change the signature of the async action creator:
It is a bit of an involved type, but you only need to define it once and are then you’re free to use it whenever it is needed.