UNPKG

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