Home > Mobile >  How to properly type `Redux` enhancer in TS?
How to properly type `Redux` enhancer in TS?

Time:02-17

I want to add meaingOfFile property to my redux state:

...
type CustomProps = 
{
    meaingOfFile: number;
}
const ResourceEnhancer: StoreEnhancer<{}, CustomProps> = (createStore) => (reducer, initialState) =>
{
    console.log("custom enhancer");
    const store = createStore(reducer, initialState);
    
    function getNewState()
    {
        return {
            ...store.getState(),
            meaingOfFile: 32,
        }
    }
    
    return { ...store, getState: getNewState};
}

const Store = configureStore({
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(LocalStorageMiddleware),
    enhancers: (defaultEnhancers) => [ResourceEnhancer, ...defaultEnhancers],
    reducer:{
        books: BooksSlice.reducer,
        shelfs: ShelfsSlice.reducer,
    }
});

But TS throw error:

TS2322: Type '<S = any, A extends Action<any> = AnyAction>(reducer: Reducer<S, A>, initialState: PreloadedState<S> | undefined) => { getState: () => S & { ...; }; dispatch: Dispatch<...>; subscribe(listener: () => void): Unsubscribe; replaceReducer(nextReducer: Reducer<...>): void; [Symbol.observable](): Observable<...>; }' is not assignable to type 'StoreEnhancerStoreCreator<{}, CustomProps>'.
  Call signature return types '{ getState: () => S & { meaingOfFile: number; }; dispatch: Dispatch<A>; subscribe(listener: () => void): Unsubscribe; replaceReducer(nextReducer: Reducer<S & {}, A>): void; [Symbol.observable](): Observable<...>; }' and 'Store<S & CustomProps, A>' are incompatible.
    The types of 'replaceReducer' are incompatible between these types.
      Type '(nextReducer: Reducer<S & {}, A>) => void' is not assignable to type '(nextReducer: Reducer<S & CustomProps, A>) => void'.
        Types of parameters 'nextReducer' and 'nextReducer' are incompatible.
          Types of parameters 'state' and 'state' are incompatible.
            Type '(S & {}) | undefined' is not assignable to type '(S & CustomProps) | undefined'.
              Type 'S & {}' is not assignable to type '(S & CustomProps) | undefined'.
                Type 'S & {}' is not assignable to type 'S & CustomProps'.
                  Property 'meaingOfFile' is missing in type '{}' but required in type 'CustomProps'.

CodePudding user response:

Unfortunately, the configureStore typings have no really working support for StoreEnhancer. If you want to add extra properties in the end, you will have to add those manually with a type cast.

In this case you can achieve the same result by just wrapping your rootReducer with a custom reducer function though.

const rootReducer = combineReducers({
        books: BooksSlice.reducer,
        shelfs: ShelfsSlice.reducer,
    }}
const enhancedReducer = (state, action) => {
  return {
    ...rootReducer(state,action),
    meaingOfFile: 32,
  }
}

const Store = configureStore({
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(LocalStorageMiddleware),
    reducer: enhancedReducer
});
  • Related