Blog>
Snippets

Strongly typed reducers with utility types

Use TypeScript utility types to create reducers with enhanced type-checking and support for state and action shape changes in Redux 5.0.0.
// State type for the counter example
interface CounterState {
    count: number;
}

// Actions types with a 'type' and an optional 'payload'
interface IncrementAction {
    type: 'INCREMENT';
}

interface DecrementAction {
    type: 'DECREMENT';
}

interface AddAction {
    type: 'ADD';
    payload: number;
}

// Create a type for all action creators to use for reducer
// Using TypeScript's Union Type here

type CounterAction = IncrementAction | DecrementAction | AddAction;

// The reducer function with strong typing for state and actions
const counterReducer = (
    state: CounterState,
    action: CounterAction
): CounterState => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        case 'ADD':
            return { count: state.count + action.payload };
        default:
            return state;
    }
};
The code defines a strongly typed reducer in TypeScript for a counter example using a state interface, action interfaces for each action type, and a union type for the action parameter of the reducer function. The use of these utility types allows for better type-checking and ensures actions are dispatched correctly within the reducer.