Prinny
Prinny

Reputation: 168

How to dynamically determine RootState type in redux toolkit with makeStore function

I am trying to get the type of my redux store in order to declare the RootState type. Up until now I was creating and exporting a store instance as specified in the redux toolkit docs and faced no problems whatsoever, but now for various reasons I want to have a makeStore function to return a new store every time I call it.

My problem is that while I have a working implementation, the type of RootState is any which results in no autocomplete recommendations.

My code is the following:

import {
    configureStore,
    combineReducers,
    EnhancedStore,
    ConfigureStoreOptions,
} from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import {
    persistStore,
    persistReducer,
    FLUSH,
    REHYDRATE,
    PAUSE,
    PERSIST,
    PURGE,
    REGISTER,
} from 'redux-persist';
import storage from 'redux-persist/lib/storage';

import { cartReducer } from '@hooks';

import appReducer from './reducer';
import rootSaga from './saga';

export const makeStore: (
    initialState?: ConfigureStoreOptions['preloadedState']
) => EnhancedStore = (initialState = {}) => {
    const persistConfig = {
        key: 'root',
        version: 1,
        storage,
    };

    const persistedReducer = persistReducer(
        persistConfig,
        combineReducers({ app: appReducer, cart: cartReducer })
    );

    const sagaMiddleware = createSagaMiddleware();

    const store = configureStore({
        reducer: persistedReducer,
        preloadedState: initialState,
        middleware: getDefaultMiddleware =>
            getDefaultMiddleware({
                thunk: false,
                serializableCheck: {
                    ignoredActions: [
                        FLUSH,
                        REHYDRATE,
                        PAUSE,
                        PERSIST,
                        PURGE,
                        REGISTER,
                    ],
                },
            }).concat(sagaMiddleware),
    });

    sagaMiddleware.run(rootSaga);

    return store;
};

const store = makeStore();
export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>; // this is "any"
export type AppDispatch = typeof store.dispatch; // this is "Dispatch<AnyAction>"

export default store;

I think the most probable cause of the problem lies in EnhancedStore which is a generic and looks like that:

export interface EnhancedStore<S = any, A extends Action = AnyAction, M extends Middlewares<S> = Middlewares<S>> extends Store<S, A> {
    /**
     * The `dispatch` method of your store, enhanced by all its middlewares.
     *
     * @inheritdoc
     */
    dispatch: DispatchForMiddlewares<M> & Dispatch<A>;
}

I am not really sure what S is supposed to be, so I don't pass anything to it and it defaults to any.

My question is, what is the best way to get the store state type when using redux-toolkit and a makeStore function?

Upvotes: 0

Views: 962

Answers (1)

phry
phry

Reputation: 44166

Just remove your return type.

The real return type is much more nuanced and you are throwing that information out of the window by assigning one yourself.

export const makeStore: (
    initialState?: ConfigureStoreOptions['preloadedState']
) = (initialState = {}) => {

Upvotes: 1

Related Questions