Blog>
Snippets

Combining Reducers with Typed Actions

Show an example of combining multiple reducers which work with their own typed actions instead of AnyAction.
// 1. Define action types
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
const ADD_TODO = 'ADD_TODO';

// 2. Create action interfaces
interface IncrementAction {
  type: typeof INCREMENT;
  payload: number;
}

interface DecrementAction {
  type: typeof DECREMENT;
  payload: number;
}

interface AddTodoAction {
  type: typeof ADD_TODO;
  text: string;
}

// Define action type that can be handled by counterReducer
type CounterAction = IncrementAction | DecrementAction;

// Define action type accepted by todosReducer
type TodoAction = AddTodoAction;

// 3. Create reducers
const counterReducer = (state = 0, action: CounterAction) => {
  switch (action.type) {
    case INCREMENT:
      return state + action.payload;
    case DECREMENT:
      return state - action.payload;
    default:
      return state;
  }
};

const todosReducer = (state: string[] = [], action: TodoAction) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.text];
    default:
      return state;
  }
};

// 4. Combine reducers
const rootReducer = Redux.combineReducers({
  counter: counterReducer,
  todos: todosReducer
});

// 5. Use the combined reducer in the Redux store
const store = Redux.createStore(rootReducer);
This example shows how to combine multiple reducers in a type-safe way using TypeScript types. Typed actions such as `IncrementAction`, `DecrementAction`, and `AddTodoAction` are used to define the types of actions that the reducers can handle. Then, the `counterReducer` and `todosReducer` functions are created, each handling a subset of the action types. Finally, these reducers are combined using `Redux.combineReducers` to create a root reducer, which is used to create the Redux store.