Home > Net >  Why typescript complains about redux slices' initialState type in reduxToolkit createSlice func
Why typescript complains about redux slices' initialState type in reduxToolkit createSlice func

Time:02-27

My createSlice() function:

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

type TransferDeckModeType = "pipetting" | "evaluation" | "editing";

var initialState: TransferDeckModeType = "pipetting";

const transfer_deck_mode = createSlice({
  name: "transfer_deck_mode",
  initialState,
  reducers: {
    setTransferDeckMode(state, action: PayloadAction<TransferDeckModeType>) {
      let newState = action.payload;
      return newState;
    },
  },
});

export const { setTransferDeckMode } = transfer_deck_mode.actions;

export default transfer_deck_mode.reducer;

I get a typescript error on setTransferDeckMode.

Type '(state: "pipetting", action: { payload: TransferDeckModeType; type: string; }) => TransferDeckModeType' is not assignable to type 'CaseReducer<"pipetting", { payload: any; type: string; }> | CaseReducerWithPrepare<"pipetting", PayloadAction<any, string, any, any>>'.
  Type '(state: "pipetting", action: { payload: TransferDeckModeType; type: string; }) => TransferDeckModeType' is not assignable to type 'CaseReducer<"pipetting", { payload: any; type: string; }>'.
    Type 'TransferDeckModeType' is not assignable to type 'void | "pipetting"'.
      Type '"evaluation"' is not assignable to type 'void | "pipetting"'.ts(2322)
(method) setTransferDeckMode(state: "pipetting", action: PayloadAction<TransferDeckModeType>): TransferDeckModeType

Where is the 'void' coming from? What is setting the type to 'void | "pipetting"'. I don't see where my state could possibly be void.

I feel like I'm missing where to declare the state of the slice, but for some reason I am blind. I thought it could be inferred from the type of initialState.

If I change the initialState type to string the error goes away.


var initialState: string = "pipetting";

But that doesn't make sense - why can't I declare the type of the initialState?

CodePudding user response:

This is the reason why the RTK docs show

var initialState = "pipetting" as TransferDeckModeType ;

instead.

TypeScript does flow analysis here. You can experiment with that in this TypeScript Playground

function something<T>(initialState: T) { return { initialState } }
type Values = 'a' | 'b'

{
var initialState: Values = 'a';
//    ^?

const derivedValue = something(initialState)
//    ^?
// due to flow analysis, TS thinks `initialState` is `'a'`
// and pins `derivedValue` to `{ initialState: "a" }`
}

{
var initialState = 'a' as Values;
//    ^?

const derivedValue = something(initialState)
//    ^?
// here we could prevent that with a type assertion, 
// telling TS to stop being "too smart"
}
  • Related