import type { Draft } from 'immer'; import type { Action, Reducer, UnknownAction } from 'redux'; import type { ActionReducerMapBuilder } from './mapBuilders'; import type { NoInfer, TypeGuard } from './tsHelpers'; /** * Defines a mapping from action types to corresponding action object shapes. * * @deprecated This should not be used manually - it is only used for internal * inference purposes and should not have any further value. * It might be removed in the future. * @public */ export type Actions = Record; export type ActionMatcherDescription = { matcher: TypeGuard; reducer: CaseReducer>; }; export type ReadonlyActionMatcherDescriptionCollection = ReadonlyArray>; export type ActionMatcherDescriptionCollection = Array>; /** * A *case reducer* is a reducer function for a specific action type. Case * reducers can be composed to full reducers using `createReducer()`. * * Unlike a normal Redux reducer, a case reducer is never called with an * `undefined` state to determine the initial state. Instead, the initial * state is explicitly specified as an argument to `createReducer()`. * * In addition, a case reducer can choose to mutate the passed-in `state` * value directly instead of returning a new state. This does not actually * cause the store state to be mutated directly; instead, thanks to * [immer](https://github.com/mweststrate/immer), the mutations are * translated to copy operations that result in a new state. * * @public */ export type CaseReducer = (state: Draft, action: A) => NoInfer | void | Draft>; /** * A mapping from action types to case reducers for `createReducer()`. * * @deprecated This should not be used manually - it is only used * for internal inference purposes and using it manually * would lead to type erasure. * It might be removed in the future. * @public */ export type CaseReducers = { [T in keyof AS]: AS[T] extends Action ? CaseReducer : void; }; export type NotFunction = T extends Function ? never : T; export type ReducerWithInitialState> = Reducer & { getInitialState: () => S; }; /** * A utility function that allows defining a reducer as a mapping from action * type to *case reducer* functions that handle these action types. The * reducer's initial state is passed as the first argument. * * @remarks * The body of every case reducer is implicitly wrapped with a call to * `produce()` from the [immer](https://github.com/mweststrate/immer) library. * This means that rather than returning a new state object, you can also * mutate the passed-in state object directly; these mutations will then be * automatically and efficiently translated into copies, giving you both * convenience and immutability. * * @overloadSummary * This function accepts a callback that receives a `builder` object as its argument. * That builder provides `addCase`, `addMatcher` and `addDefaultCase` functions that may be * called to define what actions this reducer will handle. * * @param initialState - `State | (() => State)`: The initial state that should be used when the reducer is called the first time. This may also be a "lazy initializer" function, which should return an initial state value when called. This will be used whenever the reducer is called with `undefined` as its state value, and is primarily useful for cases like reading initial state from `localStorage`. * @param builderCallback - `(builder: Builder) => void` A callback that receives a *builder* object to define * case reducers via calls to `builder.addCase(actionCreatorOrType, reducer)`. * @example ```ts import { createAction, createReducer, UnknownAction, PayloadAction, } from "@reduxjs/toolkit"; const increment = createAction("increment"); const decrement = createAction("decrement"); function isActionWithNumberPayload( action: UnknownAction ): action is PayloadAction { return typeof action.payload === "number"; } const reducer = createReducer( { counter: 0, sumOfNumberPayloads: 0, unhandledActions: 0, }, (builder) => { builder .addCase(increment, (state, action) => { // action is inferred correctly here state.counter += action.payload; }) // You can chain calls, or have separate `builder.addCase()` lines each time .addCase(decrement, (state, action) => { state.counter -= action.payload; }) // You can apply a "matcher function" to incoming actions .addMatcher(isActionWithNumberPayload, (state, action) => {}) // and provide a default case if no other handlers matched .addDefaultCase((state, action) => {}); } ); ``` * @public */ export declare function createReducer>(initialState: S | (() => S), mapOrBuilderCallback: (builder: ActionReducerMapBuilder) => void): ReducerWithInitialState;