1 | import type { Draft } from 'immer';
|
2 | import type { AnyAction, Action, Reducer } from 'redux';
|
3 | import type { ActionReducerMapBuilder } from './mapBuilders';
|
4 | import 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 | */
|
13 | export declare type Actions<T extends keyof any = string> = Record<T, Action>;
|
14 | /**
|
15 | * @deprecated use `TypeGuard` instead
|
16 | */
|
17 | export interface ActionMatcher<A extends AnyAction> {
|
18 | (action: AnyAction): action is A;
|
19 | }
|
20 | export declare type ActionMatcherDescription<S, A extends AnyAction> = {
|
21 | matcher: ActionMatcher<A>;
|
22 | reducer: CaseReducer<S, NoInfer<A>>;
|
23 | };
|
24 | export declare type ReadonlyActionMatcherDescriptionCollection<S> = ReadonlyArray<ActionMatcherDescription<S, any>>;
|
25 | export declare type ActionMatcherDescriptionCollection<S> = Array<ActionMatcherDescription<S, any>>;
|
26 | /**
|
27 | * A *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 | */
|
42 | export declare type CaseReducer<S = any, A extends Action = AnyAction> = (state: Draft<S>, action: A) => NoInfer<S> | void | Draft<NoInfer<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 | */
|
52 | export declare type CaseReducers<S, AS extends Actions> = {
|
53 | [T in keyof AS]: AS[T] extends Action ? CaseReducer<S, AS[T]> : void;
|
54 | };
|
55 | export declare type NotFunction<T> = T extends Function ? never : T;
|
56 | export 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
|
82 | import {
|
83 | createAction,
|
84 | createReducer,
|
85 | AnyAction,
|
86 | PayloadAction,
|
87 | } from "@reduxjs/toolkit";
|
88 |
|
89 | const increment = createAction<number>("increment");
|
90 | const decrement = createAction<number>("decrement");
|
91 |
|
92 | function isActionWithNumberPayload(
|
93 | action: AnyAction
|
94 | ): action is PayloadAction<number> {
|
95 | return typeof action.payload === "number";
|
96 | }
|
97 |
|
98 | const 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 | */
|
123 | export 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
|
149 | const 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)
|
156 | const initialState = () => 0
|
157 | const 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
|
166 | const increment = createAction('increment')
|
167 | const decrement = createAction('decrement')
|
168 |
|
169 | const counterReducer = createReducer(0, {
|
170 | [increment]: (state, action) => state + action.payload,
|
171 | [decrement.type]: (state, action) => state - action.payload
|
172 | })
|
173 | ```
|
174 | * @public
|
175 | */
|
176 | export 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>;
|