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"
}