In my Redux store, I am initializing a persistedReducer
which takes the redux-persist config and "rootReducer":
client/src/redux/store.ts
:
import { configureStore } from '@reduxjs/toolkit';import { persistStore, persistReducer } from 'redux-persist';import storage from 'redux-persist/lib/storage';import autoMergeLevel2 from 'redux-persist/es/stateReconciler/autoMergeLevel2';import rootReducer from './rootReducer'const persistConfig = { key: 'root', storage, stateReconciler: autoMergeLevel2,}const persistedReducer = persistReducer(persistConfig, rootReducer)export const store = configureStore({ reducer: persistedReducer});export const persistor = persistStore(store);export type RootState = ReturnType<typeof store.getState>;export type AppDispatch = typeof store.dispatch;
The rootReducer itself is being declared and exported like so:
client/src/redux/rootReducer.ts
:
import { combineReducers } from "@reduxjs/toolkit";import { IUserState } from "../interfaces/user";import userSlice from "./features/userSlice";export interface RootState { user: IUserState;}const rootReducer = combineReducers({ user: userSlice.reducer,});export default rootReducer;
The userSlice
reducer we are importing and adding to the rootReducer looks like this:
client/src/redux/features/userSlice.ts
:
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";import { IUserState } from "../../interfaces/user";import { useSelector } from "react-redux";import userApi from "../../apis/user";import { RootState } from "../store";const initialState: IUserState = { _id: "", ipAddress: "", createdAt: "", alignment: "", loading: false, error: "",};export const getUser = createAsyncThunk("user/getUser", async (_, thunkApi) => { try { const response = await userApi.getUser(); return response; } catch (error) { throw thunkApi.rejectWithValue({ error: "user not initialized" }); }});export const updateUser = createAsyncThunk<IUserState, any, { state: RootState }>("user/updateUser", async (data: any, thunkApi) => { console.log("document", data); try { const user = useSelector((state: RootState) => state.user); const response = await userApi.updateUser(user, data); return response; } catch (error) { throw thunkApi.rejectWithValue({ error: "user not updated" }); } });const userSlice = createSlice({ name: "userData", initialState, reducers: { getUser: (state, action: PayloadAction<IUserState>) => { state = Object.assign(state, action.payload); return state; }, updateUser: (state, action: PayloadAction<IUserState>) => { state = Object.assign(state, action.payload); return state; }, }, extraReducers: (builder) => { builder.addCase(getUser.fulfilled, (state, action) => { state = Object.assign(state, action.payload); state.loading = false; state.error = ""; }); builder.addCase(getUser.pending, (state) => { state.loading = true; state.error = ""; }); builder.addCase(getUser.rejected, (state, action) => { state.loading = false; state.error = action.error.message || "user not initialized"; }); },});export const { getUser: getUserAction, updateUser: updateUserAction } = userSlice.actions;export default userSlice;
The user state interface is imported from client/src/interfaces/user.ts
, and looks like this:
export type IUserState = { _id: string ipAddress: string createdAt: string alignment: string loading: boolean error: string}
The error I'm encountering in my client output states:
Argument of type 'Reducer<{ user: IUserState; }, UnknownAction, Partial<{ user: IUserState | undefined; }>>' is not assignable to parameter of type 'Reducer<unknown, UnknownAction, unknown>'. Types of parameters 'state' and 'state' are incompatible. Type 'unknown' is not assignable to type '{ user: IUserState; } | Partial<{ user: IUserState | undefined; }> | undefined'
There is a separate error from the Typescript compiler in my updateUser
asyncThunk which says Property 'user' does not exist on type 'PersistPartial'
. I am not certain if this is related to the terminal error that's complaining about a type mismatch with the Reducer. Casting rootReducer
as any
obviously makes the error go away, but I'd like to avoid that, if possible. It seems like this may be an issue with the way I am defining the RootState interface.