createSlice.d.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import type { Reducer } from 'redux';
  2. import type { ActionCreatorWithoutPayload, PayloadAction, PayloadActionCreator, PrepareAction, _ActionCreatorWithPreparedPayload } from './createAction';
  3. import type { CaseReducer, CaseReducers } from './createReducer';
  4. import type { ActionReducerMapBuilder } from './mapBuilders';
  5. import type { NoInfer } from './tsHelpers';
  6. /**
  7. * An action creator attached to a slice.
  8. *
  9. * @deprecated please use PayloadActionCreator directly
  10. *
  11. * @public
  12. */
  13. export declare type SliceActionCreator<P> = PayloadActionCreator<P>;
  14. /**
  15. * The return value of `createSlice`
  16. *
  17. * @public
  18. */
  19. export 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. */
  49. export 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. interface RejectedAction extends Action {
  78. error: Error
  79. }
  80. function isRejectedAction(action: AnyAction): action is RejectedAction {
  81. return action.type.endsWith('rejected')
  82. }
  83. createSlice({
  84. name: 'counter',
  85. initialState: 0,
  86. reducers: {},
  87. extraReducers: builder => {
  88. builder
  89. .addCase(incrementBy, (state, action) => {
  90. // action is inferred correctly here if using TS
  91. })
  92. // You can chain calls, or have separate `builder.addCase()` lines each time
  93. .addCase(decrement, (state, action) => {})
  94. // You can match a range of action types
  95. .addMatcher(
  96. isRejectedAction,
  97. // `action` will be inferred as a RejectedAction due to isRejectedAction being defined as a type guard
  98. (state, action) => {}
  99. )
  100. // and provide a default case if no other handlers matched
  101. .addDefaultCase((state, action) => {})
  102. }
  103. })
  104. ```
  105. */
  106. extraReducers?: CaseReducers<NoInfer<State>, any> | ((builder: ActionReducerMapBuilder<NoInfer<State>>) => void);
  107. }
  108. /**
  109. * A CaseReducer with a `prepare` method.
  110. *
  111. * @public
  112. */
  113. export declare type CaseReducerWithPrepare<State, Action extends PayloadAction> = {
  114. reducer: CaseReducer<State, Action>;
  115. prepare: PrepareAction<Action['payload']>;
  116. };
  117. /**
  118. * The type describing a slice's `reducers` option.
  119. *
  120. * @public
  121. */
  122. export declare type SliceCaseReducers<State> = {
  123. [K: string]: CaseReducer<State, PayloadAction<any>> | CaseReducerWithPrepare<State, PayloadAction<any, string, any, any>>;
  124. };
  125. declare type SliceActionType<SliceName extends string, ActionName extends keyof any> = ActionName extends string | number ? `${SliceName}/${ActionName}` : string;
  126. /**
  127. * Derives the slice's `actions` property from the `reducers` options
  128. *
  129. * @public
  130. */
  131. export declare type CaseReducerActions<CaseReducers extends SliceCaseReducers<any>, SliceName extends string> = {
  132. [Type in keyof CaseReducers]: CaseReducers[Type] extends {
  133. prepare: any;
  134. } ? ActionCreatorForCaseReducerWithPrepare<CaseReducers[Type], SliceActionType<SliceName, Type>> : ActionCreatorForCaseReducer<CaseReducers[Type], SliceActionType<SliceName, Type>>;
  135. };
  136. /**
  137. * Get a `PayloadActionCreator` type for a passed `CaseReducerWithPrepare`
  138. *
  139. * @internal
  140. */
  141. declare type ActionCreatorForCaseReducerWithPrepare<CR extends {
  142. prepare: any;
  143. }, Type extends string> = _ActionCreatorWithPreparedPayload<CR['prepare'], Type>;
  144. /**
  145. * Get a `PayloadActionCreator` type for a passed `CaseReducer`
  146. *
  147. * @internal
  148. */
  149. declare type ActionCreatorForCaseReducer<CR, Type extends string> = CR extends (state: any, action: infer Action) => any ? Action extends {
  150. payload: infer P;
  151. } ? PayloadActionCreator<P, Type> : ActionCreatorWithoutPayload<Type> : ActionCreatorWithoutPayload<Type>;
  152. /**
  153. * Extracts the CaseReducers out of a `reducers` object, even if they are
  154. * tested into a `CaseReducerWithPrepare`.
  155. *
  156. * @internal
  157. */
  158. declare type SliceDefinedCaseReducers<CaseReducers extends SliceCaseReducers<any>> = {
  159. [Type in keyof CaseReducers]: CaseReducers[Type] extends {
  160. reducer: infer Reducer;
  161. } ? Reducer : CaseReducers[Type];
  162. };
  163. /**
  164. * Used on a SliceCaseReducers object.
  165. * Ensures that if a CaseReducer is a `CaseReducerWithPrepare`, that
  166. * the `reducer` and the `prepare` function use the same type of `payload`.
  167. *
  168. * Might do additional such checks in the future.
  169. *
  170. * This type is only ever useful if you want to write your own wrapper around
  171. * `createSlice`. Please don't use it otherwise!
  172. *
  173. * @public
  174. */
  175. export declare type ValidateSliceCaseReducers<S, ACR extends SliceCaseReducers<S>> = ACR & {
  176. [T in keyof ACR]: ACR[T] extends {
  177. reducer(s: S, action?: infer A): any;
  178. } ? {
  179. prepare(...a: never[]): Omit<A, 'type'>;
  180. } : {};
  181. };
  182. /**
  183. * A function that accepts an initial state, an object full of reducer
  184. * functions, and a "slice name", and automatically generates
  185. * action creators and action types that correspond to the
  186. * reducers and state.
  187. *
  188. * The `reducer` argument is passed to `createReducer()`.
  189. *
  190. * @public
  191. */
  192. export declare function createSlice<State, CaseReducers extends SliceCaseReducers<State>, Name extends string = string>(options: CreateSliceOptions<State, CaseReducers, Name>): Slice<State, CaseReducers, Name>;
  193. export {};