10

I'm doing a redux-toolkit tutorial with typescript. But I'm a typescript beginner.

I don't know what the problem is here. Please give me your insight.

This is an error message. : TS2322: Type 'number' is not assignable to type 'void | State | WritableDraft'.

import {CaseReducer, createSlice, PayloadAction} from "@reduxjs/toolkit";

type State = {
  value: number
}
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => state.value + action.payload; // error line

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    increment,
    decrement: state => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    },
  },
})

export const {increment, decrement, incrementByAmount} = counterSlice.actions;

export default counterSlice.reducer;

3 Answers 3

10

An arrow function without curly braces around it is an implied return. So you are returning state.value + action.payload which is a number.

Redux Toolkit allows you to either return a new state (type State | WritableDraft<State> at the time of this answer, or type State | Draft<State> in newer versions of RTK) or modify the draft state and not return anything (type void). You get a Typescript error because returning number is neither or these.

You likely want to modify the draft state, so you need curly braces around your function body so that you aren't returning anything.


These three functions are all valid. Ordered from least to most verbose:

  1. You can increment the value directly using the addition assignment operator +=
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => {
  state.value += action.payload;
}
  1. You can assign a new value to the state.value property with assignment operator =
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => {
  state.value = state.value + action.payload;
}
  1. (Not recommended) You can return an entirely new state. I am using parentheses around curly braces to return an object with the property value.
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => ({
  value: state.value + action.payload
});

If there were properties other than value you would need to copy them like {...state, value: newValue } which is what you see in traditional Redux reducers. Redux Toolkit makes options 1 and 2 available so that you don't have to do this. But if you chose to return a new state then it must be a complete state.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your detailed explanation!! This problem was my lack of understanding of JavaScript and Redux.
@Linda Paiste may I know what's the writabledraft is. soz I did try to find what that is but couldn't find it anywhere?
@kevinTHEprogrammer the WritableDraft type comes from immer, which is the package that Redux Toolkit uses under the hood for immutable updates. WritableDraft used to be re-exported by Redux Toolkit, but it looks like now they have switched to using the immer Draft type instead.
0

CaseReducer return value must be void | State | WritableDraft while your expression:

(state, action) => state.value + action.payload

Is a function that returns a number. The solution is to add the void operator before the return value to set it to undefined.

(state, action) => void (state.value += action.payload)

4 Comments

That would still do noting though. Make it (state, action) => { state.value += action.payload } or (state, action) => { state.value = state.value + action.payload }
@phry I'm not sure what you mean, but it works in this codesandbox. Also here is the typescript playground
It has no more type error, but it also does nothing on runtime as it adds two numbers and throws away the result. The intention of the question asker was to add the two numbers and reassign them to state.value.
@phry ooh I finally got what you mean. Thanks for correcting me. I was focusing more about fixing the type error than the logic itself.
0

I resolved this by updating my typescript version to recommended version

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.