Next.js + TypeScript项目中Redux Store替代any的正确类型定义及消除@ts-ignore处TypeScript错误的方法
Let's resolve both the any type for your store variable and eliminate the need for the // @ts-ignore comment on createWrapper. Here's how to do it properly:
Step 1: Define Core Type Interfaces
First, we'll derive the root state type directly from your combined reducers (so you don't have to manually maintain it) and extend the Redux Store type to include the __persistor property added by redux-persist.
Add these imports and type definitions at the top of your file:
import { Store } from 'redux'; import { MakeStore, createWrapper } from 'next-redux-wrapper'; import { Persistor } from 'redux-persist'; // Derive RootState from the combined reducer (auto-updates when you add/remove reducers) export type RootState = ReturnType<typeof combinedReducer>; // Extend Redux Store to include the __persistor property for client-side persistence export type AppStore = Store<RootState> & { __persistor?: Persistor; };
Step 2: Fix the Store Variable Type
Replace the vague any type with our new AppStore type (we add undefined since the store is only assigned on the client side):
export let store: AppStore | undefined;
Step 3: Correct the makeStore Type Signature
Update makeStore to use the MakeStore type from next-redux-wrapper (which enforces the correct return type), and remove the // @ts-ignore comment by explicitly typing createWrapper:
const makeStore: MakeStore<AppStore> = ({ isServer }) => { // ... existing makeStore logic remains the same ... }; // No more @ts-ignore needed - we explicitly specify the store type export const wrapper = createWrapper<AppStore>(makeStore);
Full Modified Code
Here's the complete ./stores/store.ts with all fixes applied:
import { createStore, applyMiddleware, combineReducers, Middleware, Store } from 'redux'; import { MakeStore, createWrapper } from 'next-redux-wrapper'; import thunkMiddleware from 'redux-thunk'; import { Persistor } from 'redux-persist'; import auth from './auth/reducer'; import userData from './user/reducer'; import userChallenges from './userChallenges/reducer'; import challenges from './challenges/reducer'; // 绑定中间件 const bindMiddleware = (middleware: Middleware[]) => { if (process.env.NODE_ENV !== 'production') { const { composeWithDevTools } = require('redux-devtools-extension'); return composeWithDevTools(applyMiddleware(...middleware)); } return applyMiddleware(...middleware); }; // 合并所有reducer const combinedReducer = combineReducers({ auth, userData, userChallenges, challenges, }); // Derive root state type from combined reducer export type RootState = ReturnType<typeof combinedReducer>; // Extend Store type to include redux-persist's persistor export type AppStore = Store<RootState> & { __persistor?: Persistor; }; // Store variable with correct type (undefined on server, AppStore on client) export let store: AppStore | undefined; // Typed makeStore function const makeStore: MakeStore<AppStore> = ({ isServer }) => { if (isServer) { // 如果是服务端,创建store return createStore(combinedReducer, bindMiddleware([thunkMiddleware])); } else { // 如果是客户端,创建可持久化的store const { persistStore, persistReducer } = require('redux-persist'); const storage = require('redux-persist/lib/storage').default; const persistConfig = { key: 'nextjs', whitelist: ['auth', 'userData'], // 仅这些reducer会被持久化,按需添加其他reducer storage, // 如有需要,使用更安全的存储方式 }; const persistedReducer = persistReducer(persistConfig, combinedReducer); // 使用现有reducer创建新的持久化reducer store = createStore(persistedReducer, bindMiddleware([thunkMiddleware])); // 重新创建store store.__persistor = persistStore(store); // 创建persistor对象并挂载到store.__persistor,以启用持久化功能 return store; } }; // Typed wrapper - no more @ts-ignore! export const wrapper = createWrapper<AppStore>(makeStore);
Key Improvements:
- Type Safety: No more
any- the store type is strictly typed based on your actual reducers. - Auto-Updating Root State:
RootStateautomatically reflects changes to your combined reducers, so you don't have to manually update it. - Eliminated Type Errors: The
createWrappernow has explicit type information, so TypeScript understands the store shape and no longer throws errors.
内容的提问来源于stack exchange,提问作者Mohammad Reza Ghasemi

