I'd like to use an union type like this to represent my slice's state when using Redux Toolkit:
type AppState = { loading: true } | { loading: false; data: number };
It seems like the usage of Immerjs in the reducer files prevents me from switching between the two Union options, e.g.:
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
const initialState: AppState = { loading: true };
export const sampleSlice = createSlice({
name: "sample",
initialState,
reducers: {
setup: (state) => {
return { loading: false, data: 5 };
},
},
});
Which gives me the following Typescript error:
Type '(state: WritableDraft<{ loading: true; }>) => { loading: false; data: number; }' is not assignable to type 'CaseReducer<{ loading: true; }, { payload: any; type: string; }> | CaseReducerWithPrepare<{ loading: true; }, PayloadAction<any, string, any, any>>'.
Is there any way to make this work? My current workaround is not using an union type to represent the state but I'm wondering if there is a workaround. I have also tried not using booleans but string literals for the loading
key but it produces the same error.
CodePudding user response:
Option 1. Provide the generic parameter types for createSlice
.
import { createSlice, SliceCaseReducers } from '@reduxjs/toolkit';
type AppState = { loading: true } | { loading: false; data: number };
const initialState: AppState = { loading: true };
type CaseReducers = SliceCaseReducers<AppState>;
export const sampleSlice = createSlice<AppState, CaseReducers>({
name: 'sample',
initialState,
reducers: {
setup: (state) => {
return { loading: false, data: 5 };
},
},
});
The state
type in case reducer:
Option 2. Cast the initial state. See Defining the Initial State Type
import { createSlice, SliceCaseReducers } from '@reduxjs/toolkit';
type AppState = { loading: true } | { loading: false; data: number };
const initialState: AppState = { loading: true };
// type CaseReducers = SliceCaseReducers<AppState>;
export const sampleSlice = createSlice({
name: 'sample',
initialState: initialState as AppState,
reducers: {
setup: (state) => {
return { loading: false, data: 5 };
},
},
});
package versions:
"@reduxjs/toolkit": "^1.6.1",
"typescript": "^4.3.5",