Open sintylapse opened 4 years ago
That's the only way it worked for me
const persistedReducer = persistReducer<IDemoState>(persistConfig, demoReducer as any);
or this way
const persistedReducer = persistReducer<any, any>(persistConfig, demoReducer);
How do you define your rootReducer
? Do you pass your State
type to combineReducers
? Example:
const rootReducer = combineReducers<RootReducerState>({
apples,
oranges
});
// somewhere in persist config
const persistedReducer = persistReducer(persistConfig, rootReducer);
I have the same problem
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from 'redux';
import { persistReducer } from 'reduxjs-toolkit-persist';
import storage from 'reduxjs-toolkit-persist/lib/storage';
import createSagaMiddleware from 'redux-saga';
import reducers from 'Reducers/index';
import sagas from 'Sagas/index';
import conf from 'Lib/conf';
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, combineReducers(reducers));
const sagaMiddleware = createSagaMiddleware();
const devMode = conf.NODE_ENV !== 'production';
export const store = configureStore({
reducer: persistedReducer,
middleware: [sagaMiddleware],
devTools: devMode,
});
sagaMiddleware.run(sagas);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
If i hover on RootState
i get any, if instead inside the configureStore
function i don't pass the persistedReducer
but simply the reducers
like below all is working and i get the types correctly on RootState
export const store = configureStore({
reducer: reducers,
middleware: [sagaMiddleware],
devTools: devMode,
});
Just came across this. Seems to be an issue with the return type of persistReducer()
.
I managed to work around it with a little bit of TS magic:
type InferState<Type> = Type extends Reducer<infer S> ? S : never;
type State<T extends typeof reducers = typeof reducers, P extends keyof T = keyof T> = {
[K in P]: InferState<T[K]>;
};
const reducers = {
[FEATURE_A_KEY]: aReducer,
[FEATURE_B_KEY]: bReducer,
};
const persistedReducer: Reducer<State, AnyAction> = persistReducer<State, AnyAction>(
persistConfig,
combineReducers(reducers)
);
@fruchtzwerg Getting this error
Argument of type '{ App: Reducer<AppState & PersistPartial, AnyAction>; Snackbar: Reducer<SnackbarState, AnyAction>; Storefront: Reducer<...>; }' is not assignable to parameter of type 'Reducer<State<{ App: Reducer<AppState & PersistPartial, AnyAction>; Snackbar: Reducer<SnackbarState, AnyAction>; Storefront: Reducer<...>; }, "Storefront" | ... 1 more ... | "Snackbar">, AnyAction>'.
Type '{ App: Reducer<AppState & PersistPartial, AnyAction>; Snackbar: Reducer<SnackbarState, AnyAction>; Storefront: Reducer<...>; }' provides no match for the signature '(state: State<{ App: Reducer<AppState & PersistPartial, AnyAction>; Snackbar: Reducer<SnackbarState, AnyAction>; Storefront: Reducer<...>; }, "Storefront" | ... 1 more ... | "Snackbar"> | undefined, action: AnyAction): State<...>'.
Maybe it's because I have nested persisted reducers. Are you using @reduxjs/toolkit
?
@Rc85 Probably the nesting, yes.
InferState
will extract the state from the reducer's generic. If you have nested reducers it will only get the first level.
I also had to remove some explicit payload types from my slices. TS can infer them properly though.
Yes, I am using @reduxjs/toolkit
Ran into this issue also while using RTK, the simplest way I found to solve it was to let Typescript infer everything from the call to persistReducer by putting the config inline there :
const persistedReducer = persistReducer({
key: 'cl',
storage,
}, combinedReducer);
Only weird thing left is that the type of persisted reducer is now Reducer<EmptyObject & MyStateType & PersistPartial>
. No idea where that EmptyObject comes from, but I can live with that.
RESOLVED
export type RootState = ReturnType<typeof rootReducer>;
When I use
persistReducer
it returnsany
type no matter how I use it, for example