1

I am setting up ts with redux and running into quite a number of issues - mostly down to my lack of knowledge, but cannot find much online. The error I am seeing is the following:

Operator '+' cannot be applied to types 'CounterState' and '1'.

The code I have is as follows:

interface CounterState {
  state: number;
}

const initialState: CounterState = {
  state: 0
}

interface Action {
  type: string;
}

export const counterReducer = (state = initialState, action: Action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
};

If I update to this it works but it seems like I don't have to define a type for the state. The following works

const initialState = 0;
interface Action {
  type: string;
}

export const counterReducer = (state = initialState, action: Action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
};
4
  • 2
    Your state is not a number. The state in your example code is an object with a property state. Instead just let CounterState be a number. (not an object), then it will work. E.g. type CounterState = number; const initialState = 0; Commented Oct 11, 2018 at 10:26
  • that works, thanks! bit confused as I thought I also had to give the state a type earlier too.Updated the question Commented Oct 11, 2018 at 11:04
  • Well you "should" give it a type. Now the state type will be inferred from the initialState. It works but it's cleaner to define it. IMO. Theese guys have some good patterns github.com/piotrwitek/react-redux-typescript-guide#reducers Commented Oct 11, 2018 at 11:41
  • would you like to add an answer as to how it should be set up. Points are there for you ;-) Commented Oct 11, 2018 at 12:28

1 Answer 1

1

It's good practise to always strongly type your reducers, both state and actions.

Here i show an example of how a proper defined reducer and store can look like together. Hope this example together with my comments helps you.

import { Reducer } from "redux"; //This is just a Type we import from Redux.

interface IncrementAction {
  type: "INCREMENT"; //Define your action names
}

interface DecrementAction {
  type: "DECREMENT"; //Define your action names
}

type PossibleCounterActions = IncrementAction | DecrementAction; 
// The actions could/should be defined in another file for clarity


type CounterState = number;

const defaultState = 0;

// We bind the variable counterReducer to the Reducer type taken from redux.
// The our reducer code gets cleaner and we know the return type and arguments.
const counterReducer: Reducer<CounterState, PossibleCounterActions> = (state = defaultState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}



// PS. This is not part of the question but it's
// a nice side-effect you can do when you have properly defined reducers.
// In the file where you create your store you can now get your store
// interface from the returntype of the redcuers using this pattern. 
const reducers = {
  counter: counterReducer
};

// Now we can get the entire store state from the declaration in the reducers.
export type IStoreState = { [k in keyof (typeof reducers)]: ReturnType<(typeof reducers)[k]> };

//More code to initialize your store.....
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.