Blog>
Snippets

Redux Thunk 3.0 with TypeScript

Illustrate how to type thunks for better maintainability and developer experience using TypeScript with Redux Thunk 3.0.
import { Action, Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';

// Define the state type
interface ExampleState {
  data: any;
}

// Define the action types
enum ExampleActionTypes {
  FETCH_START = 'FETCH_START',
  FETCH_SUCCESS = 'FETCH_SUCCESS',
  FETCH_ERROR = 'FETCH_ERROR',
}

// Define the action interfaces
interface FetchStartAction extends Action<ExampleActionTypes.FETCH_START> {}

interface FetchSuccessAction extends Action<ExampleActionTypes.FETCH_SUCCESS> {
  payload: any;
}

interface FetchErrorAction extends Action<ExampleActionTypes.FETCH_ERROR> {
  error: Error;
}

// Combine the action types
type ExampleActions = FetchStartAction | FetchSuccessAction | FetchErrorAction;
This code sets up the TypeScript interfaces for our state and actions. It demonstrates how to type the state of the Redux store as well as actions with specific types and payloads. It uses enums to make action types more reliable and less prone to typos.
// Action creators
export const fetchStart = (): FetchStartAction => ({
  type: ExampleActionTypes.FETCH_START,
});

export const fetchSuccess = (payload: any): FetchSuccessAction => ({
  type: ExampleActionTypes.FETCH_SUCCESS,
  payload,
});

export const fetchError = (error: Error): FetchErrorAction => ({
  type: ExampleActionTypes.FETCH_ERROR,
  error,
});
These are the action creators for each of the actions. The functions return the action objects with the appropriate type and, when necessary, a payload or an error.
// Thunk action
export const fetchExampleData = ():
  ThunkAction<void, ExampleState, unknown, ExampleActions> =>
  async (dispatch: Dispatch) => {
    try {
      dispatch(fetchStart());
      // Replace with actual async call
      const response = await fetch('/api/data');
      const data = await response.json();
      dispatch(fetchSuccess(data));
    } catch (error) {
      dispatch(fetchError(error as Error));
    }
  };
This thunk action uses 'ThunkAction' from redux-thunk to define a function that can dispatch actions. It's a thunk because it returns a function that then gets executed by the thunk middleware. This example makes an asynchronous API call and dispatches the appropriate actions based on whether the call succeeds or fails.