Understanding typings of redux-thunk action

christineoo avatar


This blog post will be focusing on explaining the TypeScript definition of ThunkAction which is used in the redux-thunk library. If you're not sure what redux-thunk is, I'd recommend reading through the why do I need this section in the redux-thunk library. Then, come back to this blog post to learn about the TypeScript definition of ThunkAction. I also highly recommend reading what is a thunk.

Hope you've check out the materials recommended above before you continue reading 👀 💭

However, if you're interested in learning TypeScript's type aliases, I think you would enjoy this blog post as well. I will be explaining how type aliases are being used in a more complex type definition.

Let's dive in head-on then by looking at the type definition of ThunkAction.

export type ThunkAction<R, S, E, A extends Action> = (
  dispatch: ThunkDispatch<S, E, A>,
  getState: () => S,
  extraArgument: E
) => R;

The definition of ThunkAction can be overwhelming and filled with generics(defined with <>). The TypeScript's type aliases is used here. Before moving further, I'd like to dig into what is type aliases first.

📝 The snippet below is taken from TypeScript handbook-advance-types(type aliases)

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
  if (typeof n === "string") {
    return n;
  else {
    return n();

// 🙆
const getNameMethod = () => 'John';
console.log(getName('Mary')); // Mary
console.log(getName(getNameMethod)); // John

// 🙅
// Using the defined type aliases you'll see an error is thrown if a wrong type is passed to getName
const getNumberMethod = () => 1;
console.log(getName(getNumberMethod)); // 🛑
/* getNumberMethod is () => number
Argument of type '() => number' is not assignable to parameter of type 'NameOrResolver'.
  Type '() => number' is not assignable to type 'NameResolver'.
    Type 'number' is not assignable to type 'string'.ts(2345)

The definition of ThunkAction is complicated and it is hard to understand how it is using TypeScript's type aliases. In this section, the ThunkAction definition will be broken down into a simpler form by referring to the (type NameResolver = () => string) definition.

export type ThunkAction<R, S, E, A extends Action> = (
  dispatch: ThunkDispatch<S, E, A>,
  getState: () => S,
  extraArgument: E
) => R;

// The simplified form of ThunkAction type definition
export type ThunkAction<generics> = (dispatch, getState, extraArgument) => ReturnType;

Now that the definition is simplified, the generics passed to ThunkAction type can be tackled more easily.

  • type ThunkAction<R>
type ThunkAction<R> = (dispatch, getState, extraArgument) => R

// This would make R the return type of the `ThunkAction` method.
  • type ThunkAction<R, S, E, A extends Action>
type ThunkAction<R, S, E, A extends Action> = (
  dispatch: ThunkDispatch<S, E, A>,
  getState: () => S,
  extraArgument: E
) => R;

  S = is the type of root state
    = is the return type of the getState() method.
  E = is the type of the extra arguments passed to the ThunkAction
  A = is the action type defined in your application.
    = it should be able to extend from Action.
      (this means that it should be an object 
      that must have a `type` field.) Action type is defined in the redux typings.

Usage example

After understanding the typings of ThunkAction, I would like to share an example of how ThunkAction can be used in your TypeScript code.

import { ThunkAction } from 'redux-thunk';
  export type AppThunk = ThunkAction<void, RootState, null, Action<string>>
  // R = void
  // S = RootState
  // E = null
  // A = Action<string>
export const fetchUser = (id: string): AppThunk => async dispatch => {
    try {
      // handle fetch success
    } catch (err) {
      // handle fetch failure

Thanks for reading and happy typings~ 👋


christineoo avatar
Written By


A web developer that is fueled by coffee ☕
Enjoyed the post?

Clap to support the author, help others find it, and make your opinion count.