Redux-toolkit: Extra properties added to store by enhancers are not getting inferred by configureStore

Created on 19 Aug 2020  路  6Comments  路  Source: reduxjs/redux-toolkit

I have a custom enhancer with the following signature:

export interface ExtraProperties<PS> {
  persistence: {
    getPersistentState: () => PS
    hydrate: (state: PS) => void
    flush: () => void
  }
}



const enhancer = (createStore: StoreEnhancerStoreCreator): StoreEnhancerStoreCreator<ExtraProperties<PS>> => {
  return <S = any, A extends Action = AnyAction>(
    reducer: Reducer<S, A>,
    preloadedState?: PreloadedState<S>
  ) => {
   ...
  }
}

However when I add this enhancer to configureStore, the type of the returned store doesn't change at all.

image

This is caused by the fact that configureStore has type parameters for the state, actions and middleware, but not for the enhancer.

image

All 6 comments

Is there anything new on this issue?

@kien8995 no - if there had been, there'd either be some comments or it'd be closed :)

Agreed that this is probably an issue, but tbh enhancers adding additional fields to the store instance is a relatively rare use case and thus not one that we've looked at.

I'm not sure if the issue here is with the underlying Redux types, or with RTK's configureStore.

If you or someone else would like to investigate, that'd be helpful.

I remember that I did look at it before one of the last releases, setting myself a time limit and didn't get anywhere close to a good solution that would not require significantly restructuring of our types. So I put it back on the backlog.

So it is still on the list "to be investigated, with a lot more time".

But as Mark said, the priority is not very high as it does not affect many of our users and usually can be dealt with by doing some manual type magic on the library consumer side.

I currently did with this workaround by use createStore from redux and it work!

import { createStore, applyMiddleware, compose } from 'redux'

export const configureStore = (
    preloadedState: Record<string, unknown> = {},
    isDebug: boolean = false
) => {
    const logMiddleware = createLogger({
        predicate: () => isDebug,
    })

    return createStore(
        createReducer(),
        preloadedState,
        compose(
            storeEnhancer,
            applyMiddleware(
                multiActionMiddleware,
                actionListenerMiddleware(actionListeners),
                logMiddleware
            )
        )
    )
}

I would try to _not_ do it that way ,because then you're losing out on all the rest of the setup that RTK's configureStore does for you.

Instead, try something like:

const _store = configureStore({/* args here */});
type BaseStore = typeof _store;

export const store = _store as BaseStore & MyOtherStoreMethods;

I've got something similar in one of my projects at work.

I'm going to say that the workaround ought to be sufficient for now. If someone wants to file a PR that improves the types for this use case, we can look at it.

Was this page helpful?
0 / 5 - 0 ratings