# Understanding the NoInfer Type Parameter in Redux createStore

> Learn about Redux createStore's NoInfer type parameter. Prevent TypeScript automatic inference to keep your store extensions correctly typed. Enhance your Redux development.

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

---

**The `NoInfer` type parameter is an internal TypeScript utility that prevents the compiler from automatically inferring generic type arguments in Redux's `createStore` function, ensuring store extensions remain explicitly typed.**

In the `reduxjs/redux` repository, the `createStore` function relies on sophisticated TypeScript generics to support store extensions—custom properties merged into the returned store object. The `NoInfer` utility type plays a critical role in maintaining type safety by blocking unwanted type inference.

## What Is the NoInfer Type Parameter?

`NoInfer` is a **conditional type utility** defined internally in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts). It uses a tuple indexing trick to make a type "non-inferable" by TypeScript's inference engine:

```typescript
// src/createStore.ts
type NoInfer<T> = [T][T extends any ? 0 : never]

```

This definition exploits the fact that TypeScript avoids inferring types that appear in **contravariant positions** or complex conditional expressions. When `NoInfer<T>` wraps a type parameter, the compiler treats `T` as explicitly provided rather than attempting to derive it from function arguments.

## Why createStore Uses NoInfer

The `createStore` function signature includes four generic parameters: `S` (state), `A` (actions), `Ext` (extensions), and `StateExt` (state extensions). The `Ext` parameter represents an object type whose properties are merged into the returned store:

```typescript
export function createStore<
  S,
  A extends Action,
  Ext extends {} = {},
  StateExt extends {} = {}
>(reducer: Reducer<S, A>, preloadedState?: S, enhancer?: StoreEnhancer<Ext, StateExt>): 
  Store<S, A, UnknownIfNonSpecific<StateExt>> & NoInfer<Ext>

```

Without `NoInfer<Ext>`, TypeScript would attempt to **infer `Ext` from the `enhancer` argument** or other parameters. Because `Ext` is only used to augment the return type—and not consumed as a function parameter in a way that constrains inference—the compiler might default it to `{}` or infer an incorrect type from context.

By wrapping the return type intersection with `NoInfer<Ext>`, Redux ensures that `Ext` must be **explicitly specified by the caller** or correctly propagated from the enhancer's type parameters, preserving the intended type augmentation.

## Practical Examples

### Basic Store Without Extensions

When creating a simple store without enhancers, `Ext` defaults to `{}` and `NoInfer` has no visible effect:

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

function counter(state = 0, action: { type: string }) {
  switch (action.type) {
    case 'inc': return state + 1
    default: return state
  }
}

// Ext defaults to {}
const store = createStore(counter)
// Type: Store<number, { type: string }>

```

### Store With Custom Extensions

When using a store enhancer that adds methods, `NoInfer` ensures the extension type propagates correctly:

```typescript
interface LoggerExtension {
  logState: () => void
}

// Explicitly provide the extension generic
const store = createStore<number, { type: string }, LoggerExtension>(counter)

// TypeScript recognizes the custom method
store.logState = () => console.log(store.getState())
store.logState() // → logs current state

```

### The Inference Problem Without NoInfer

If `createStore` omitted `NoInfer`, TypeScript might incorrectly narrow `Ext` based on optional parameters:

```typescript
// Hypothetical signature without NoInfer
function createStoreWithInfer<S, A extends Action, Ext extends {} = {}>(
  reducer: Reducer<S, A>,
  extensionFactory?: () => Ext
): Store<S, A> & Ext {
  // implementation...
}

// TypeScript infers Ext = {} because extensionFactory is optional
const store = createStoreWithInfer(counter)
// Resulting type lacks extension properties even if provided later

```

Using `NoInfer<Ext>` blocks this unwanted inference, forcing the type system to respect the explicit generic parameter.

## Key Implementation Files

The `NoInfer` utility and its application appear in these critical source files:

- **[`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts)** – Defines the `NoInfer<T>` utility type and applies it to the return type of `createStore` and `legacy_createStore`
- **[`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts)** – Contains the `Store` interface that gets augmented by the `Ext` generic
- **[`src/types/actions.ts`](https://github.com/reduxjs/redux/blob/main/src/types/actions.ts)** – Provides the base `Action` type used in the store's generic constraints

## Summary

- **`NoInfer<T>`** is an internal TypeScript utility in Redux that prevents automatic type inference for specific generic parameters.
- It ensures that **store extension types** (`Ext`) must be explicitly provided rather than inferred from function arguments.
- The type uses a tuple indexing trick (`[T][T extends any ? 0 : never]`) to block TypeScript's inference engine.
- This mechanism maintains **type safety** when using store enhancers that add custom methods or properties to the store object.

## Frequently Asked Questions

### What does the NoInfer type parameter do in Redux?

The `NoInfer` type parameter prevents TypeScript from automatically inferring the `Ext` (extension) generic in `createStore`. Without it, the compiler might incorrectly infer the extension type from optional parameters or default it to `{}`, causing custom store methods to lose their type information. By wrapping the return type with `NoInfer<Ext>`, Redux ensures that extension types remain exactly as specified by the developer.

### Is NoInfer part of Redux's public API?

No, `NoInfer` is an **internal implementation detail** and is not exported from the Redux package. Developers using Redux do not interact with `NoInfer` directly; it operates behind the scenes to maintain type correctness when `createStore` returns a store object augmented with extension properties. The utility is defined privately in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) and only appears in the return type signature.

### Why can't TypeScript infer store extensions automatically?

TypeScript's inference engine prioritizes types derived from **function parameters** over return type expectations. Since the `Ext` generic only appears in the return type (as part of the intersection `Store & NoInfer<Ext>`) and not in a parameter position that constrains it, the compiler has no reliable source for inference. If `NoInfer` were absent, TypeScript would likely default `Ext` to `{}` or infer it from unrelated context, breaking the type augmentation pattern used by store enhancers.

### How does the NoInfer utility type actually work?

`NoInfer<T>` uses a **conditional type within a tuple index** to block inference: `[T][T extends any ? 0 : never]`. This construction places `T` in a contravariant position within a conditional expression, which signals to TypeScript's inference engine that this type should not be inferred from usage. The result is that `T` must be explicitly provided at the call site, preserving the intended type structure for store extensions.