UNPKG

7.67 kBTypeScriptView Raw
1import type { Reducer } from 'redux';
2import type { ActionCreatorWithoutPayload, PayloadAction, PayloadActionCreator, PrepareAction, _ActionCreatorWithPreparedPayload } from './createAction';
3import type { CaseReducer, CaseReducers } from './createReducer';
4import type { ActionReducerMapBuilder } from './mapBuilders';
5import type { NoInfer } from './tsHelpers';
6/**
7 * An action creator attached to a slice.
8 *
9 * @deprecated please use PayloadActionCreator directly
10 *
11 * @public
12 */
13export declare type SliceActionCreator<P> = PayloadActionCreator<P>;
14/**
15 * The return value of `createSlice`
16 *
17 * @public
18 */
19export interface Slice<State = any, CaseReducers extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string> {
20 /**
21 * The slice name.
22 */
23 name: Name;
24 /**
25 * The slice's reducer.
26 */
27 reducer: Reducer<State>;
28 /**
29 * Action creators for the types of actions that are handled by the slice
30 * reducer.
31 */
32 actions: CaseReducerActions<CaseReducers, Name>;
33 /**
34 * The individual case reducer functions that were passed in the `reducers` parameter.
35 * This enables reuse and testing if they were defined inline when calling `createSlice`.
36 */
37 caseReducers: SliceDefinedCaseReducers<CaseReducers>;
38 /**
39 * Provides access to the initial state value given to the slice.
40 * If a lazy state initializer was provided, it will be called and a fresh value returned.
41 */
42 getInitialState: () => State;
43}
44/**
45 * Options for `createSlice()`.
46 *
47 * @public
48 */
49export interface CreateSliceOptions<State = any, CR extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string> {
50 /**
51 * The slice's name. Used to namespace the generated action types.
52 */
53 name: Name;
54 /**
55 * 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`.
56 */
57 initialState: State | (() => State);
58 /**
59 * A mapping from action types to action-type-specific *case reducer*
60 * functions. For every action type, a matching action creator will be
61 * generated using `createAction()`.
62 */
63 reducers: ValidateSliceCaseReducers<State, CR>;
64 /**
65 * A callback that receives a *builder* object to define
66 * case reducers via calls to `builder.addCase(actionCreatorOrType, reducer)`.
67 *
68 * Alternatively, a mapping from action types to action-type-specific *case reducer*
69 * functions. These reducers should have existing action types used
70 * as the keys, and action creators will _not_ be generated.
71 *
72 * @example
73 ```ts
74 import { createAction, createSlice, Action, AnyAction } from '@reduxjs/toolkit'
75 const incrementBy = createAction<number>('incrementBy')
76 const decrement = createAction('decrement')
77
78 interface RejectedAction extends Action {
79 error: Error
80 }
81
82 function isRejectedAction(action: AnyAction): action is RejectedAction {
83 return action.type.endsWith('rejected')
84 }
85
86 createSlice({
87 name: 'counter',
88 initialState: 0,
89 reducers: {},
90 extraReducers: builder => {
91 builder
92 .addCase(incrementBy, (state, action) => {
93 // action is inferred correctly here if using TS
94 })
95 // You can chain calls, or have separate `builder.addCase()` lines each time
96 .addCase(decrement, (state, action) => {})
97 // You can match a range of action types
98 .addMatcher(
99 isRejectedAction,
100 // `action` will be inferred as a RejectedAction due to isRejectedAction being defined as a type guard
101 (state, action) => {}
102 )
103 // and provide a default case if no other handlers matched
104 .addDefaultCase((state, action) => {})
105 }
106 })
107 ```
108 */
109 extraReducers?: CaseReducers<NoInfer<State>, any> | ((builder: ActionReducerMapBuilder<NoInfer<State>>) => void);
110}
111/**
112 * A CaseReducer with a `prepare` method.
113 *
114 * @public
115 */
116export declare type CaseReducerWithPrepare<State, Action extends PayloadAction> = {
117 reducer: CaseReducer<State, Action>;
118 prepare: PrepareAction<Action['payload']>;
119};
120/**
121 * The type describing a slice's `reducers` option.
122 *
123 * @public
124 */
125export declare type SliceCaseReducers<State> = {
126 [K: string]: CaseReducer<State, PayloadAction<any>> | CaseReducerWithPrepare<State, PayloadAction<any, string, any, any>>;
127};
128declare type SliceActionType<SliceName extends string, ActionName extends keyof any> = ActionName extends string | number ? `${SliceName}/${ActionName}` : string;
129/**
130 * Derives the slice's `actions` property from the `reducers` options
131 *
132 * @public
133 */
134export declare type CaseReducerActions<CaseReducers extends SliceCaseReducers<any>, SliceName extends string> = {
135 [Type in keyof CaseReducers]: CaseReducers[Type] extends {
136 prepare: any;
137 } ? ActionCreatorForCaseReducerWithPrepare<CaseReducers[Type], SliceActionType<SliceName, Type>> : ActionCreatorForCaseReducer<CaseReducers[Type], SliceActionType<SliceName, Type>>;
138};
139/**
140 * Get a `PayloadActionCreator` type for a passed `CaseReducerWithPrepare`
141 *
142 * @internal
143 */
144declare type ActionCreatorForCaseReducerWithPrepare<CR extends {
145 prepare: any;
146}, Type extends string> = _ActionCreatorWithPreparedPayload<CR['prepare'], Type>;
147/**
148 * Get a `PayloadActionCreator` type for a passed `CaseReducer`
149 *
150 * @internal
151 */
152declare type ActionCreatorForCaseReducer<CR, Type extends string> = CR extends (state: any, action: infer Action) => any ? Action extends {
153 payload: infer P;
154} ? PayloadActionCreator<P, Type> : ActionCreatorWithoutPayload<Type> : ActionCreatorWithoutPayload<Type>;
155/**
156 * Extracts the CaseReducers out of a `reducers` object, even if they are
157 * tested into a `CaseReducerWithPrepare`.
158 *
159 * @internal
160 */
161declare type SliceDefinedCaseReducers<CaseReducers extends SliceCaseReducers<any>> = {
162 [Type in keyof CaseReducers]: CaseReducers[Type] extends {
163 reducer: infer Reducer;
164 } ? Reducer : CaseReducers[Type];
165};
166/**
167 * Used on a SliceCaseReducers object.
168 * Ensures that if a CaseReducer is a `CaseReducerWithPrepare`, that
169 * the `reducer` and the `prepare` function use the same type of `payload`.
170 *
171 * Might do additional such checks in the future.
172 *
173 * This type is only ever useful if you want to write your own wrapper around
174 * `createSlice`. Please don't use it otherwise!
175 *
176 * @public
177 */
178export declare type ValidateSliceCaseReducers<S, ACR extends SliceCaseReducers<S>> = ACR & {
179 [T in keyof ACR]: ACR[T] extends {
180 reducer(s: S, action?: infer A): any;
181 } ? {
182 prepare(...a: never[]): Omit<A, 'type'>;
183 } : {};
184};
185/**
186 * A function that accepts an initial state, an object full of reducer
187 * functions, and a "slice name", and automatically generates
188 * action creators and action types that correspond to the
189 * reducers and state.
190 *
191 * The `reducer` argument is passed to `createReducer()`.
192 *
193 * @public
194 */
195export declare function createSlice<State, CaseReducers extends SliceCaseReducers<State>, Name extends string = string>(options: CreateSliceOptions<State, CaseReducers, Name>): Slice<State, CaseReducers, Name>;
196export {};