The best proper type for store in Next.js project + TypeScript

Viewed 39

What's the proper type for store in export let store: any; instead of any? Consider I've used @ts-igore for the last line. What can I do to get rid of the TypeScript error for that too? I mentioned the boilerplates I used in this project in the first three lines. This is a part of a Next.js project + TypeScript + redux-presist.

// ./stores/store.ts

// Boilerplate for Redux + Next.js: https://github.com/vercel/next.js/tree/canary/examples/with-redux-wrapper
// Boilerplate for Redux Persist: https://github.com/fazlulkarimweb/with-next-redux-wrapper-redux-persist/blob/master/store/store.js
// For more information check next-redux-wrapper: https://github.com/kirill-konshin/next-redux-wrapper

import {
  createStore,
  applyMiddleware,
  combineReducers,
  Middleware,
} from 'redux';
import { createWrapper } from 'next-redux-wrapper';
import thunkMiddleware from 'redux-thunk';

import auth from './auth/reducer';
import userData from './user/reducer';
import userChallenges from './userChallenges/reducer';
import challenges from './challenges/reducer';

// Binding middleware
const bindMiddleware = (middleware: Middleware[]) => {
  if (process.env.NODE_ENV !== 'production') {
    const { composeWithDevTools } = require('redux-devtools-extension');
    return composeWithDevTools(applyMiddleware(...middleware));
  }
  return applyMiddleware(...middleware);
};

// Combining all reducers
const combinedReducer = combineReducers({
  auth,
  userData,
  userChallenges,
  challenges,
});

export let store: any;

const makeStore = ({ isServer }: { isServer: boolean }) => {
  if (isServer) {
    //If it's on server side, create a store
    return createStore(combinedReducer, bindMiddleware([thunkMiddleware]));
  } else {
    //If it's on client side, create a store which will persist
    const { persistStore, persistReducer } = require('redux-persist');
    const storage = require('redux-persist/lib/storage').default;

    const persistConfig = {
      key: 'nextjs',
      whitelist: ['auth', 'userData'], // only these reducers will be persisted, add other reducers if needed
      storage, // if needed, use a safer storage
    };

    const persistedReducer = persistReducer(persistConfig, combinedReducer); // Create a new reducer with our existing reducer

    store = createStore(persistedReducer, bindMiddleware([thunkMiddleware])); // Creating the store again

    store.__persistor = persistStore(store); // This creates a persistor object & push that persisted object to .__persistor, so that we can avail the persistability feature

    return store;
  }
};

// Export the wrapper & wrap the pages/_app.js with this wrapper only
// @ts-ignore
export const wrapper = createWrapper(makeStore);
2 Answers

My understanding of redux is that the store is the data object. So it's entirely defined by you.

interface StoreType {
  label: string;
}

Suppose the above is your data structure

 export const makeStore = (context: Context) => {
     const sagaMiddleware = createSagaMiddleware();
      const store = createStore(
        rootReducer,
        // list of your middlewares here
        bindMiddleware([thunk, sagaMiddleware])
      );
      // in case someone else uses saga
      (store as SagaStore).sagaTask = sagaMiddleware.run(rootSaga);

  return store;
};

Your rootReducer:

const rootReducer = combineReducers({
  productList: productListReducer,
  cart: cartReducer,
  user: userLoginReducer,
  userDetail: userDetailReducer,
});

and your RootState

export type RootState = ReturnType<typeof rootReducer>;
Related