# How to Extend Redux Store with Custom Methods via Enhancers

> Learn how to extend your Redux store with custom methods by using store enhancers. Augment your store's functionality and behavior effortlessly while maintaining the Redux API.

- Repository: [Redux/redux](https://github.com/reduxjs/redux)
- Tags: how-to-guide
- Published: 2026-03-05

---

**A store enhancer is a higher-order function that wraps the store creator to augment the returned store object with custom methods, extra state, or additional behavior while preserving the core Redux API contract.**

Extending a Redux store with custom methods requires understanding the store enhancer pattern implemented in the reduxjs/redux repository. While middleware intercepts actions, store enhancers modify the store creation process itself to inject additional functionality. This approach allows you to add methods like `reset()` or merge extra state fields while maintaining full type safety through TypeScript generics.

## Understanding Store Enhancers

A store enhancer is officially typed as `StoreEnhancer<Ext, StateExt>` defined in [[`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts)](https://github.com/reduxjs/redux/blob/master/src/types/store.ts). This higher-order function receives a `next` store creator and returns a new creator that produces a store with merged extensions.

The type definition (lines 200-226) uses generics to track both method extensions (`Ext`) and state extensions (`StateExt`), ensuring TypeScript recognizes your custom additions. When `createStore` detects an enhancer argument, it delegates creation entirely to that enhancer.

From [[`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts)](https://github.com/reduxjs/redux/blob/master/src/createStore.ts) (lines 31-43):

```typescript
if (typeof enhancer !== 'undefined') {
  return enhancer(createStore)(reducer, preloadedState)
}

```

This delegation allows the enhancer to invoke the original `createStore`, receive the base store object, and return an augmented version that spreads the original store plus your custom extensions.

## Adding Custom Methods to the Store

### Creating a Reset Method Enhancer

To extend the Redux store with a custom `reset` method, define an enhancer that captures the initial state and returns a new store object with the added functionality:

```typescript
import { createStore, StoreEnhancer } from 'redux'

const resetEnhancer: StoreEnhancer<{ reset(): void }> = createStore => (
  reducer,
  preloadedState
) => {
  const store = createStore(reducer, preloadedState)
  const initialState = store.getState()

  return {
    ...store,
    reset() {
      store.replaceReducer(() => initialState)
      store.dispatch({ type: '@@RESET' })
    }
  }
}

const store = createStore(counterReducer, resetEnhancer)
store.reset() // TypeScript recognizes this method

```

The generic `<{ reset(): void }>` tells TypeScript that `store.reset` exists on the enhanced store type. The original `store` methods (`dispatch`, `getState`, `subscribe`) remain unchanged and fully functional.

## Extending Store State Shape

### Injecting Additional State Fields

You can also use enhancers to ensure specific state fields always exist by wrapping the reducer and preloaded state. This pattern uses the second generic parameter `StateExt` to extend the state type:

```typescript
import { createStore, StoreEnhancer, Reducer } from 'redux'

interface ExtraState {
  extraFlag: boolean
}

function withExtraState<S, A extends { type: string }, PreloadedState = S>(
  reducer: Reducer<S, A, PreloadedState>
): Reducer<S & ExtraState, A, PreloadedState & ExtraState> {
  return (state, action) => ({
    ...reducer(state as any, action),
    extraFlag: true
  })
}

const extraStateEnhancer: StoreEnhancer<{}, ExtraState> = createStore => (
  reducer,
  preloadedState
) => {
  const wrappedReducer = withExtraState(reducer as any)
  const wrappedPreloaded = preloadedState
    ? { ...(preloadedState as any), extraFlag: true }
    : undefined

  return createStore(wrappedReducer, wrappedPreloaded as any)
}

const store = createStore(rootReducer, extraStateEnhancer)
const state = store.getState()
state.extraFlag // boolean (TypeScript knows this exists)

```

The enhancer wraps the original reducer to merge `extraFlag` into every state update, ensuring the property persists regardless of user actions.

## Composing Multiple Enhancers

You can stack multiple enhancers using the `compose` utility (the same function used for middleware), applying them right-to-left:

```typescript
import { compose, applyMiddleware, createStore } from 'redux'
import thunk from 'redux-thunk'

const composedEnhancer = compose(
  resetEnhancer,
  extraStateEnhancer,
  applyMiddleware(thunk)
)

const store = createStore(rootReducer, composedEnhancer)

```

The resulting store includes both the `reset` method and the `extraFlag` state field while maintaining thunk middleware support. TypeScript correctly infers the intersection of all extensions through the composed `StoreEnhancer` type.

## Key Implementation Files

- **[[`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts)](https://github.com/reduxjs/redux/blob/master/src/createStore.ts)** – Contains the core logic that detects and invokes enhancers at lines 31-43.
- **[[`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts)](https://github.com/reduxjs/redux/blob/master/src/types/store.ts)** – Defines `StoreEnhancer<Ext, StateExt>` and `StoreCreator` types (lines 200-226) that enable type-safe extensions.
- **[[`test/typescript/enhancers.test-d.ts`](https://github.com/reduxjs/redux/blob/main/test/typescript/enhancers.test-d.ts)](https://github.com/reduxjs/redux/blob/master/test/typescript/enhancers.test-d.ts)** – Test suite demonstrating real-world usage of enhancers with TypeScript.
- **[[`src/applyMiddleware.ts`](https://github.com/reduxjs/redux/blob/main/src/applyMiddleware.ts)](https://github.com/reduxjs/redux/blob/master/src/applyMiddleware.ts)** – Reference implementation of a built-in enhancer that follows the same pattern for middleware integration.

## Summary

- **Store enhancers** are higher-order functions that wrap `createStore` to return augmented store objects with custom methods or state.
- The **`StoreEnhancer<Ext, StateExt>`** type in [`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts) provides compile-time safety for your extensions.
- **Composition** via `compose()` allows stacking multiple enhancers, including `applyMiddleware`, in a single store creation call.
- **TypeScript integration** requires specifying method extensions in the first generic parameter and state extensions in the second to maintain full type inference.
- **Core Redux behavior** remains intact because enhancers spread the original store object before adding custom properties.

## Frequently Asked Questions

### What is the difference between a store enhancer and middleware?

Middleware intercepts dispatched actions to add logging, async handling, or side effects, but cannot add methods to the store object itself. Store enhancers wrap the entire store creation process to add custom methods like `reset()` or modify the state shape at the root level. According to the reduxjs/redux source code, `applyMiddleware` is actually implemented as a store enhancer in [`src/applyMiddleware.ts`](https://github.com/reduxjs/redux/blob/main/src/applyMiddleware.ts), demonstrating that enhancers are the lower-level primitive.

### Can I use multiple store enhancers together?

Yes. Multiple enhancers compose naturally using the `compose` utility function, applying them right-to-left. Each enhancer receives the output of the previous one, allowing you to stack functionality such as custom methods, state extensions, and middleware in a single `createStore` call.

### How do I add TypeScript types for custom store methods?

Define your enhancer with the `StoreEnhancer<Ext, StateExt>` type from [`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts). Pass an object type describing your custom methods as the first generic argument (e.g., `StoreEnhancer<{ reset(): void }>`). This propagates through the composition chain so TypeScript recognizes the methods on the final store instance, as verified in [`test/typescript/enhancers.test-d.ts`](https://github.com/reduxjs/redux/blob/main/test/typescript/enhancers.test-d.ts).

### Does adding custom methods break Redux DevTools or other plugins?

No. Because enhancers spread the original store object (`...store`) before adding properties, all standard Redux APIs (`dispatch`, `getState`, `subscribe`, `replaceReducer`) remain intact and accessible. Redux DevTools and other libraries that expect a standard Redux store will continue to function normally, though they will not automatically recognize your custom methods unless explicitly typed.