UNPKG

8.45 kBTypeScriptView Raw
1import type { Draft } from 'immer';
2import type { AnyAction, Action, Reducer } from 'redux';
3import type { ActionReducerMapBuilder } from './mapBuilders';
4import type { NoInfer } from './tsHelpers';
5/**
6 * Defines a mapping from action types to corresponding action object shapes.
7 *
8 * @deprecated This should not be used manually - it is only used for internal
9 * inference purposes and should not have any further value.
10 * It might be removed in the future.
11 * @public
12 */
13export declare type Actions<T extends keyof any = string> = Record<T, Action>;
14/**
15 * @deprecated use `TypeGuard` instead
16 */
17export interface ActionMatcher<A extends AnyAction> {
18 (action: AnyAction): action is A;
19}
20export declare type ActionMatcherDescription<S, A extends AnyAction> = {
21 matcher: ActionMatcher<A>;
22 reducer: CaseReducer<S, NoInfer<A>>;
23};
24export declare type ReadonlyActionMatcherDescriptionCollection<S> = ReadonlyArray<ActionMatcherDescription<S, any>>;
25export declare type ActionMatcherDescriptionCollection<S> = Array<ActionMatcherDescription<S, any>>;
26/**
27 * An *case reducer* is a reducer function for a specific action type. Case
28 * reducers can be composed to full reducers using `createReducer()`.
29 *
30 * Unlike a normal Redux reducer, a case reducer is never called with an
31 * `undefined` state to determine the initial state. Instead, the initial
32 * state is explicitly specified as an argument to `createReducer()`.
33 *
34 * In addition, a case reducer can choose to mutate the passed-in `state`
35 * value directly instead of returning a new state. This does not actually
36 * cause the store state to be mutated directly; instead, thanks to
37 * [immer](https://github.com/mweststrate/immer), the mutations are
38 * translated to copy operations that result in a new state.
39 *
40 * @public
41 */
42export declare type CaseReducer<S = any, A extends Action = AnyAction> = (state: Draft<S>, action: A) => S | void | Draft<S>;
43/**
44 * A mapping from action types to case reducers for `createReducer()`.
45 *
46 * @deprecated This should not be used manually - it is only used
47 * for internal inference purposes and using it manually
48 * would lead to type erasure.
49 * It might be removed in the future.
50 * @public
51 */
52export declare type CaseReducers<S, AS extends Actions> = {
53 [T in keyof AS]: AS[T] extends Action ? CaseReducer<S, AS[T]> : void;
54};
55export declare type NotFunction<T> = T extends Function ? never : T;
56export declare type ReducerWithInitialState<S extends NotFunction<any>> = Reducer<S> & {
57 getInitialState: () => S;
58};
59/**
60 * A utility function that allows defining a reducer as a mapping from action
61 * type to *case reducer* functions that handle these action types. The
62 * reducer's initial state is passed as the first argument.
63 *
64 * @remarks
65 * The body of every case reducer is implicitly wrapped with a call to
66 * `produce()` from the [immer](https://github.com/mweststrate/immer) library.
67 * This means that rather than returning a new state object, you can also
68 * mutate the passed-in state object directly; these mutations will then be
69 * automatically and efficiently translated into copies, giving you both
70 * convenience and immutability.
71 *
72 * @overloadSummary
73 * This overload accepts a callback function that receives a `builder` object as its argument.
74 * That builder provides `addCase`, `addMatcher` and `addDefaultCase` functions that may be
75 * called to define what actions this reducer will handle.
76 *
77 * @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`.
78 * @param builderCallback - `(builder: Builder) => void` A callback that receives a *builder* object to define
79 * case reducers via calls to `builder.addCase(actionCreatorOrType, reducer)`.
80 * @example
81```ts
82import {
83 createAction,
84 createReducer,
85 AnyAction,
86 PayloadAction,
87} from "@reduxjs/toolkit";
88
89const increment = createAction<number>("increment");
90const decrement = createAction<number>("decrement");
91
92function isActionWithNumberPayload(
93 action: AnyAction
94): action is PayloadAction<number> {
95 return typeof action.payload === "number";
96}
97
98const reducer = createReducer(
99 {
100 counter: 0,
101 sumOfNumberPayloads: 0,
102 unhandledActions: 0,
103 },
104 (builder) => {
105 builder
106 .addCase(increment, (state, action) => {
107 // action is inferred correctly here
108 state.counter += action.payload;
109 })
110 // You can chain calls, or have separate `builder.addCase()` lines each time
111 .addCase(decrement, (state, action) => {
112 state.counter -= action.payload;
113 })
114 // You can apply a "matcher function" to incoming actions
115 .addMatcher(isActionWithNumberPayload, (state, action) => {})
116 // and provide a default case if no other handlers matched
117 .addDefaultCase((state, action) => {});
118 }
119);
120```
121 * @public
122 */
123export declare function createReducer<S extends NotFunction<any>>(initialState: S | (() => S), builderCallback: (builder: ActionReducerMapBuilder<S>) => void): ReducerWithInitialState<S>;
124/**
125 * A utility function that allows defining a reducer as a mapping from action
126 * type to *case reducer* functions that handle these action types. The
127 * reducer's initial state is passed as the first argument.
128 *
129 * The body of every case reducer is implicitly wrapped with a call to
130 * `produce()` from the [immer](https://github.com/mweststrate/immer) library.
131 * This means that rather than returning a new state object, you can also
132 * mutate the passed-in state object directly; these mutations will then be
133 * automatically and efficiently translated into copies, giving you both
134 * convenience and immutability.
135 *
136 * @overloadSummary
137 * This overload accepts an object where the keys are string action types, and the values
138 * are case reducer functions to handle those action types.
139 *
140 * @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`.
141 * @param actionsMap - An object mapping from action types to _case reducers_, each of which handles one specific action type.
142 * @param actionMatchers - An array of matcher definitions in the form `{matcher, reducer}`.
143 * All matching reducers will be executed in order, independently if a case reducer matched or not.
144 * @param defaultCaseReducer - A "default case" reducer that is executed if no case reducer and no matcher
145 * reducer was executed for this action.
146 *
147 * @example
148```js
149const counterReducer = createReducer(0, {
150 increment: (state, action) => state + action.payload,
151 decrement: (state, action) => state - action.payload
152})
153
154// Alternately, use a "lazy initializer" to provide the initial state
155// (works with either form of createReducer)
156const initialState = () => 0
157const counterReducer = createReducer(initialState, {
158 increment: (state, action) => state + action.payload,
159 decrement: (state, action) => state - action.payload
160})
161```
162
163 * Action creators that were generated using [`createAction`](./createAction) may be used directly as the keys here, using computed property syntax:
164
165```js
166const increment = createAction('increment')
167const decrement = createAction('decrement')
168
169const counterReducer = createReducer(0, {
170 [increment]: (state, action) => state + action.payload,
171 [decrement.type]: (state, action) => state - action.payload
172})
173```
174 * @public
175 */
176export declare function createReducer<S extends NotFunction<any>, CR extends CaseReducers<S, any> = CaseReducers<S, any>>(initialState: S | (() => S), actionsMap: CR, actionMatchers?: ActionMatcherDescriptionCollection<S>, defaultCaseReducer?: CaseReducer<S>): ReducerWithInitialState<S>;