react redux reducer typescript error with combineReducers function

Viewed 116

I try to implement a redux store for my application.

Here is my app.ts (main store file):

import { combineReducers, compose, createStore, Reducer } from 'redux';

import * as fromBarcode from './reducers/barcode';

export interface AppState {
  barcode: fromBarcode.State;
}

const composeEnhancers: typeof compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const rootReducer: Reducer<AppState> = combineReducers({
  barcode: fromBarcode.reducer,
});

export const store = createStore(rootReducer, composeEnhancers());

Here is ./reducers/barcode file:

import * as actions from '../actions/barcode';

export interface State {
  token: string | null;
}

const initialState: State = {
  token: null,
};

export const reducer = (state: State = initialState, action: actions.BarcodeTypes): State => {
  switch (action.type) {
    case actions.SET_TOKEN:
      return { ...state, token: action.payload.token };
    default:
      return state;
  }
};

Here is ../actions/barcode file:

export const SET_TOKEN = '[Barcode] Set token';

// --- Interface --- //

export interface SetToken {
  type: typeof SET_TOKEN;
  payload: { token: string | null };
}

// --- Action creators --- //

export const setToken = (token: string | null): SetToken => {
  return {
    type: SET_TOKEN,
    payload: { token },
  };
};

export type BarcodeTypes = SetToken;

However, for some reason I don't know and cannot understand I get the following error from app.ts file:

Type 'Reducer<CombinedState<{ barcode: State; }>, SetToken>' is not assignable to type 'Reducer<AppState, AnyAction>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'AnyAction' is not assignable to type 'SetToken'

Any help?

Also, I observe that once I change the following line (line 11) in the reducer file: export const reducer = (state: State = initialState, action: actions.BarcodeTypes): State => { to export const reducer = (state: State = initialState, action: any): State => {

The error disappears

1 Answers

One possible way to solve this would be to introduce a union type for all of you app actions:

// union of all actions accepted by the barcode reducer, here just SetToken
type BarcodeAction =
    | SetToken;

// union of all actions in the app, exported from different slices
type AppAction =
    | BarcodeAction;

And then type your root reducer, providing the AppAction type as the second type parameter:

const rootReducer: Reducer<AppState, AppAction> = combineReducers({
  barcode: barcode.reducer,
});
Related