mapBuilders.d.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import type { Action, AnyAction } from 'redux';
  2. import type { CaseReducer, CaseReducers, ActionMatcherDescriptionCollection } from './createReducer';
  3. import type { TypeGuard } from './tsHelpers';
  4. export interface TypedActionCreator<Type extends string> {
  5. (...args: any[]): Action<Type>;
  6. type: Type;
  7. }
  8. /**
  9. * A builder for an action <-> reducer map.
  10. *
  11. * @public
  12. */
  13. export interface ActionReducerMapBuilder<State> {
  14. /**
  15. * Adds a case reducer to handle a single exact action type.
  16. * @remarks
  17. * All calls to `builder.addCase` must come before any calls to `builder.addMatcher` or `builder.addDefaultCase`.
  18. * @param actionCreator - Either a plain action type string, or an action creator generated by [`createAction`](./createAction) that can be used to determine the action type.
  19. * @param reducer - The actual case reducer function.
  20. */
  21. addCase<ActionCreator extends TypedActionCreator<string>>(actionCreator: ActionCreator, reducer: CaseReducer<State, ReturnType<ActionCreator>>): ActionReducerMapBuilder<State>;
  22. /**
  23. * Adds a case reducer to handle a single exact action type.
  24. * @remarks
  25. * All calls to `builder.addCase` must come before any calls to `builder.addMatcher` or `builder.addDefaultCase`.
  26. * @param actionCreator - Either a plain action type string, or an action creator generated by [`createAction`](./createAction) that can be used to determine the action type.
  27. * @param reducer - The actual case reducer function.
  28. */
  29. addCase<Type extends string, A extends Action<Type>>(type: Type, reducer: CaseReducer<State, A>): ActionReducerMapBuilder<State>;
  30. /**
  31. * Allows you to match your incoming actions against your own filter function instead of only the `action.type` property.
  32. * @remarks
  33. * If multiple matcher reducers match, all of them will be executed in the order
  34. * they were defined in - even if a case reducer already matched.
  35. * All calls to `builder.addMatcher` must come after any calls to `builder.addCase` and before any calls to `builder.addDefaultCase`.
  36. * @param matcher - A matcher function. In TypeScript, this should be a [type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
  37. * function
  38. * @param reducer - The actual case reducer function.
  39. *
  40. * @example
  41. ```ts
  42. import {
  43. createAction,
  44. createReducer,
  45. AsyncThunk,
  46. AnyAction,
  47. } from "@reduxjs/toolkit";
  48. type GenericAsyncThunk = AsyncThunk<unknown, unknown, any>;
  49. type PendingAction = ReturnType<GenericAsyncThunk["pending"]>;
  50. type RejectedAction = ReturnType<GenericAsyncThunk["rejected"]>;
  51. type FulfilledAction = ReturnType<GenericAsyncThunk["fulfilled"]>;
  52. const initialState: Record<string, string> = {};
  53. const resetAction = createAction("reset-tracked-loading-state");
  54. function isPendingAction(action: AnyAction): action is PendingAction {
  55. return action.type.endsWith("/pending");
  56. }
  57. const reducer = createReducer(initialState, (builder) => {
  58. builder
  59. .addCase(resetAction, () => initialState)
  60. // matcher can be defined outside as a type predicate function
  61. .addMatcher(isPendingAction, (state, action) => {
  62. state[action.meta.requestId] = "pending";
  63. })
  64. .addMatcher(
  65. // matcher can be defined inline as a type predicate function
  66. (action): action is RejectedAction => action.type.endsWith("/rejected"),
  67. (state, action) => {
  68. state[action.meta.requestId] = "rejected";
  69. }
  70. )
  71. // matcher can just return boolean and the matcher can receive a generic argument
  72. .addMatcher<FulfilledAction>(
  73. (action) => action.type.endsWith("/fulfilled"),
  74. (state, action) => {
  75. state[action.meta.requestId] = "fulfilled";
  76. }
  77. );
  78. });
  79. ```
  80. */
  81. addMatcher<A>(matcher: TypeGuard<A> | ((action: any) => boolean), reducer: CaseReducer<State, A extends AnyAction ? A : A & AnyAction>): Omit<ActionReducerMapBuilder<State>, 'addCase'>;
  82. /**
  83. * Adds a "default case" reducer that is executed if no case reducer and no matcher
  84. * reducer was executed for this action.
  85. * @param reducer - The fallback "default case" reducer function.
  86. *
  87. * @example
  88. ```ts
  89. import { createReducer } from '@reduxjs/toolkit'
  90. const initialState = { otherActions: 0 }
  91. const reducer = createReducer(initialState, builder => {
  92. builder
  93. // .addCase(...)
  94. // .addMatcher(...)
  95. .addDefaultCase((state, action) => {
  96. state.otherActions++
  97. })
  98. })
  99. ```
  100. */
  101. addDefaultCase(reducer: CaseReducer<State, AnyAction>): {};
  102. }
  103. export declare function executeReducerBuilderCallback<S>(builderCallback: (builder: ActionReducerMapBuilder<S>) => void): [
  104. CaseReducers<S, any>,
  105. ActionMatcherDescriptionCollection<S>,
  106. CaseReducer<S, AnyAction> | undefined
  107. ];