123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- import type { Action, UnknownAction, Reducer } from 'redux';
- import type { Selector } from 'reselect';
- import type { ActionCreatorWithoutPayload, PayloadAction, PayloadActionCreator, PrepareAction, _ActionCreatorWithPreparedPayload } from './createAction';
- import type { CaseReducer } from './createReducer';
- import type { ActionReducerMapBuilder } from './mapBuilders';
- import type { Id } from './tsHelpers';
- import type { InjectConfig } from './combineSlices';
- import type { AsyncThunk, AsyncThunkConfig, AsyncThunkOptions, AsyncThunkPayloadCreator, OverrideThunkApiConfigs } from './createAsyncThunk';
- import { createAsyncThunk as _createAsyncThunk } from './createAsyncThunk';
- declare const asyncThunkSymbol: unique symbol;
- export declare const asyncThunkCreator: {
- [asyncThunkSymbol]: typeof _createAsyncThunk;
- };
- interface InjectIntoConfig<NewReducerPath extends string> extends InjectConfig {
- reducerPath?: NewReducerPath;
- }
- /**
- * The return value of `createSlice`
- *
- * @public
- */
- export interface Slice<State = any, CaseReducers extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string, ReducerPath extends string = Name, Selectors extends SliceSelectors<State> = SliceSelectors<State>> {
- /**
- * The slice name.
- */
- name: Name;
- /**
- * The slice reducer path.
- */
- reducerPath: ReducerPath;
- /**
- * The slice's reducer.
- */
- reducer: Reducer<State>;
- /**
- * Action creators for the types of actions that are handled by the slice
- * reducer.
- */
- actions: CaseReducerActions<CaseReducers, Name>;
- /**
- * The individual case reducer functions that were passed in the `reducers` parameter.
- * This enables reuse and testing if they were defined inline when calling `createSlice`.
- */
- caseReducers: SliceDefinedCaseReducers<CaseReducers>;
- /**
- * Provides access to the initial state value given to the slice.
- * If a lazy state initializer was provided, it will be called and a fresh value returned.
- */
- getInitialState: () => State;
- /**
- * Get localised slice selectors (expects to be called with *just* the slice's state as the first parameter)
- */
- getSelectors(this: this): Id<SliceDefinedSelectors<State, Selectors, State>>;
- /**
- * Get globalised slice selectors (`selectState` callback is expected to receive first parameter and return slice state)
- */
- getSelectors<RootState>(this: this, selectState: (this: this, rootState: RootState) => State): Id<SliceDefinedSelectors<State, Selectors, RootState>>;
- /**
- * Selectors that assume the slice's state is `rootState[slice.reducerPath]` (which is usually the case)
- *
- * Equivalent to `slice.getSelectors((state: RootState) => state[slice.reducerPath])`.
- */
- selectors: Id<SliceDefinedSelectors<State, Selectors, {
- [K in ReducerPath]: State;
- }>>;
- /**
- * Inject slice into provided reducer (return value from `combineSlices`), and return injected slice.
- */
- injectInto<NewReducerPath extends string = ReducerPath>(this: this, injectable: {
- inject: (slice: {
- reducerPath: string;
- reducer: Reducer;
- }, config?: InjectConfig) => void;
- }, config?: InjectIntoConfig<NewReducerPath>): InjectedSlice<State, CaseReducers, Name, NewReducerPath, Selectors>;
- /**
- * Select the slice state, using the slice's current reducerPath.
- *
- * Will throw an error if slice is not found.
- */
- selectSlice(this: this, state: {
- [K in ReducerPath]: State;
- }): State;
- }
- /**
- * A slice after being called with `injectInto(reducer)`.
- *
- * Selectors can now be called with an `undefined` value, in which case they use the slice's initial state.
- */
- interface InjectedSlice<State = any, CaseReducers extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string, ReducerPath extends string = Name, Selectors extends SliceSelectors<State> = SliceSelectors<State>> extends Omit<Slice<State, CaseReducers, Name, ReducerPath, Selectors>, 'getSelectors' | 'selectors'> {
- /**
- * Get localised slice selectors (expects to be called with *just* the slice's state as the first parameter)
- */
- getSelectors(): Id<SliceDefinedSelectors<State, Selectors, State | undefined>>;
- /**
- * Get globalised slice selectors (`selectState` callback is expected to receive first parameter and return slice state)
- */
- getSelectors<RootState>(selectState: (this: this, rootState: RootState) => State | undefined): Id<SliceDefinedSelectors<State, Selectors, RootState>>;
- /**
- * Selectors that assume the slice's state is `rootState[slice.name]` (which is usually the case)
- *
- * Equivalent to `slice.getSelectors((state: RootState) => state[slice.name])`.
- */
- selectors: Id<SliceDefinedSelectors<State, Selectors, {
- [K in ReducerPath]?: State | undefined;
- }>>;
- /**
- * Select the slice state, using the slice's current reducerPath.
- *
- * Returns initial state if slice is not found.
- */
- selectSlice(state: {
- [K in ReducerPath]?: State | undefined;
- }): State;
- }
- /**
- * Options for `createSlice()`.
- *
- * @public
- */
- export interface CreateSliceOptions<State = any, CR extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string, ReducerPath extends string = Name, Selectors extends SliceSelectors<State> = SliceSelectors<State>> {
- /**
- * The slice's name. Used to namespace the generated action types.
- */
- name: Name;
- /**
- * The slice's reducer path. Used when injecting into a combined slice reducer.
- */
- reducerPath?: ReducerPath;
- /**
- * 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`.
- */
- initialState: State | (() => State);
- /**
- * A mapping from action types to action-type-specific *case reducer*
- * functions. For every action type, a matching action creator will be
- * generated using `createAction()`.
- */
- reducers: ValidateSliceCaseReducers<State, CR> | ((creators: ReducerCreators<State>) => CR);
- /**
- * A callback that receives a *builder* object to define
- * case reducers via calls to `builder.addCase(actionCreatorOrType, reducer)`.
- *
- *
- * @example
- ```ts
- import { createAction, createSlice, Action } from '@reduxjs/toolkit'
- const incrementBy = createAction<number>('incrementBy')
- const decrement = createAction('decrement')
-
- interface RejectedAction extends Action {
- error: Error
- }
-
- function isRejectedAction(action: Action): action is RejectedAction {
- return action.type.endsWith('rejected')
- }
-
- createSlice({
- name: 'counter',
- initialState: 0,
- reducers: {},
- extraReducers: builder => {
- builder
- .addCase(incrementBy, (state, action) => {
- // action is inferred correctly here if using TS
- })
- // You can chain calls, or have separate `builder.addCase()` lines each time
- .addCase(decrement, (state, action) => {})
- // You can match a range of action types
- .addMatcher(
- isRejectedAction,
- // `action` will be inferred as a RejectedAction due to isRejectedAction being defined as a type guard
- (state, action) => {}
- )
- // and provide a default case if no other handlers matched
- .addDefaultCase((state, action) => {})
- }
- })
- ```
- */
- extraReducers?: (builder: ActionReducerMapBuilder<State>) => void;
- /**
- * A map of selectors that receive the slice's state and any additional arguments, and return a result.
- */
- selectors?: Selectors;
- }
- export declare enum ReducerType {
- reducer = "reducer",
- reducerWithPrepare = "reducerWithPrepare",
- asyncThunk = "asyncThunk"
- }
- interface ReducerDefinition<T extends ReducerType = ReducerType> {
- _reducerDefinitionType: T;
- }
- export interface CaseReducerDefinition<S = any, A extends Action = UnknownAction> extends CaseReducer<S, A>, ReducerDefinition<ReducerType.reducer> {
- }
- /**
- * A CaseReducer with a `prepare` method.
- *
- * @public
- */
- export type CaseReducerWithPrepare<State, Action extends PayloadAction> = {
- reducer: CaseReducer<State, Action>;
- prepare: PrepareAction<Action['payload']>;
- };
- export interface CaseReducerWithPrepareDefinition<State, Action extends PayloadAction> extends CaseReducerWithPrepare<State, Action>, ReducerDefinition<ReducerType.reducerWithPrepare> {
- }
- export interface AsyncThunkSliceReducerConfig<State, ThunkArg extends any, Returned = unknown, ThunkApiConfig extends AsyncThunkConfig = {}> {
- pending?: CaseReducer<State, ReturnType<AsyncThunk<Returned, ThunkArg, ThunkApiConfig>['pending']>>;
- rejected?: CaseReducer<State, ReturnType<AsyncThunk<Returned, ThunkArg, ThunkApiConfig>['rejected']>>;
- fulfilled?: CaseReducer<State, ReturnType<AsyncThunk<Returned, ThunkArg, ThunkApiConfig>['fulfilled']>>;
- settled?: CaseReducer<State, ReturnType<AsyncThunk<Returned, ThunkArg, ThunkApiConfig>['rejected' | 'fulfilled']>>;
- options?: AsyncThunkOptions<ThunkArg, ThunkApiConfig>;
- }
- export interface AsyncThunkSliceReducerDefinition<State, ThunkArg extends any, Returned = unknown, ThunkApiConfig extends AsyncThunkConfig = {}> extends AsyncThunkSliceReducerConfig<State, ThunkArg, Returned, ThunkApiConfig>, ReducerDefinition<ReducerType.asyncThunk> {
- payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, ThunkApiConfig>;
- }
- /**
- * Providing these as part of the config would cause circular types, so we disallow passing them
- */
- type PreventCircular<ThunkApiConfig> = {
- [K in keyof ThunkApiConfig]: K extends 'state' | 'dispatch' ? never : ThunkApiConfig[K];
- };
- interface AsyncThunkCreator<State, CurriedThunkApiConfig extends PreventCircular<AsyncThunkConfig> = PreventCircular<AsyncThunkConfig>> {
- <ThunkArg extends any, Returned = unknown>(payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, CurriedThunkApiConfig>, config?: AsyncThunkSliceReducerConfig<State, ThunkArg, Returned, CurriedThunkApiConfig>): AsyncThunkSliceReducerDefinition<State, ThunkArg, Returned, CurriedThunkApiConfig>;
- <ThunkArg extends any, Returned = unknown, ThunkApiConfig extends PreventCircular<AsyncThunkConfig> = {}>(payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, ThunkApiConfig>, config?: AsyncThunkSliceReducerConfig<State, ThunkArg, Returned, ThunkApiConfig>): AsyncThunkSliceReducerDefinition<State, ThunkArg, Returned, ThunkApiConfig>;
- withTypes<ThunkApiConfig extends PreventCircular<AsyncThunkConfig>>(): AsyncThunkCreator<State, OverrideThunkApiConfigs<CurriedThunkApiConfig, ThunkApiConfig>>;
- }
- export interface ReducerCreators<State> {
- reducer(caseReducer: CaseReducer<State, PayloadAction>): CaseReducerDefinition<State, PayloadAction>;
- reducer<Payload>(caseReducer: CaseReducer<State, PayloadAction<Payload>>): CaseReducerDefinition<State, PayloadAction<Payload>>;
- asyncThunk: AsyncThunkCreator<State>;
- preparedReducer<Prepare extends PrepareAction<any>>(prepare: Prepare, reducer: CaseReducer<State, ReturnType<_ActionCreatorWithPreparedPayload<Prepare>>>): {
- _reducerDefinitionType: ReducerType.reducerWithPrepare;
- prepare: Prepare;
- reducer: CaseReducer<State, ReturnType<_ActionCreatorWithPreparedPayload<Prepare>>>;
- };
- }
- /**
- * The type describing a slice's `reducers` option.
- *
- * @public
- */
- export type SliceCaseReducers<State> = Record<string, CaseReducerDefinition<State, PayloadAction<any>> | CaseReducerWithPrepareDefinition<State, PayloadAction<any, string, any, any>> | AsyncThunkSliceReducerDefinition<State, any, any, any>> | Record<string, CaseReducer<State, PayloadAction<any>> | CaseReducerWithPrepare<State, PayloadAction<any, string, any, any>>>;
- /**
- * The type describing a slice's `selectors` option.
- */
- export type SliceSelectors<State> = {
- [K: string]: (sliceState: State, ...args: any[]) => any;
- };
- type SliceActionType<SliceName extends string, ActionName extends keyof any> = ActionName extends string | number ? `${SliceName}/${ActionName}` : string;
- /**
- * Derives the slice's `actions` property from the `reducers` options
- *
- * @public
- */
- export type CaseReducerActions<CaseReducers extends SliceCaseReducers<any>, SliceName extends string> = {
- [Type in keyof CaseReducers]: CaseReducers[Type] extends infer Definition ? Definition extends {
- prepare: any;
- } ? ActionCreatorForCaseReducerWithPrepare<Definition, SliceActionType<SliceName, Type>> : Definition extends AsyncThunkSliceReducerDefinition<any, infer ThunkArg, infer Returned, infer ThunkApiConfig> ? AsyncThunk<Returned, ThunkArg, ThunkApiConfig> : Definition extends {
- reducer: any;
- } ? ActionCreatorForCaseReducer<Definition['reducer'], SliceActionType<SliceName, Type>> : ActionCreatorForCaseReducer<Definition, SliceActionType<SliceName, Type>> : never;
- };
- /**
- * Get a `PayloadActionCreator` type for a passed `CaseReducerWithPrepare`
- *
- * @internal
- */
- type ActionCreatorForCaseReducerWithPrepare<CR extends {
- prepare: any;
- }, Type extends string> = _ActionCreatorWithPreparedPayload<CR['prepare'], Type>;
- /**
- * Get a `PayloadActionCreator` type for a passed `CaseReducer`
- *
- * @internal
- */
- type ActionCreatorForCaseReducer<CR, Type extends string> = CR extends (state: any, action: infer Action) => any ? Action extends {
- payload: infer P;
- } ? PayloadActionCreator<P, Type> : ActionCreatorWithoutPayload<Type> : ActionCreatorWithoutPayload<Type>;
- /**
- * Extracts the CaseReducers out of a `reducers` object, even if they are
- * tested into a `CaseReducerWithPrepare`.
- *
- * @internal
- */
- type SliceDefinedCaseReducers<CaseReducers extends SliceCaseReducers<any>> = {
- [Type in keyof CaseReducers]: CaseReducers[Type] extends infer Definition ? Definition extends AsyncThunkSliceReducerDefinition<any, any, any, any> ? Id<Pick<Required<Definition>, 'fulfilled' | 'rejected' | 'pending' | 'settled'>> : Definition extends {
- reducer: infer Reducer;
- } ? Reducer : Definition : never;
- };
- type RemappedSelector<S extends Selector, NewState> = S extends Selector<any, infer R, infer P> ? Selector<NewState, R, P> & {
- unwrapped: S;
- } : never;
- /**
- * Extracts the final selector type from the `selectors` object.
- *
- * Removes the `string` index signature from the default value.
- */
- type SliceDefinedSelectors<State, Selectors extends SliceSelectors<State>, RootState> = {
- [K in keyof Selectors as string extends K ? never : K]: RemappedSelector<Selectors[K], RootState>;
- };
- /**
- * Used on a SliceCaseReducers object.
- * Ensures that if a CaseReducer is a `CaseReducerWithPrepare`, that
- * the `reducer` and the `prepare` function use the same type of `payload`.
- *
- * Might do additional such checks in the future.
- *
- * This type is only ever useful if you want to write your own wrapper around
- * `createSlice`. Please don't use it otherwise!
- *
- * @public
- */
- export type ValidateSliceCaseReducers<S, ACR extends SliceCaseReducers<S>> = ACR & {
- [T in keyof ACR]: ACR[T] extends {
- reducer(s: S, action?: infer A): any;
- } ? {
- prepare(...a: never[]): Omit<A, 'type'>;
- } : {};
- };
- interface BuildCreateSliceConfig {
- creators?: {
- asyncThunk?: typeof asyncThunkCreator;
- };
- }
- export declare function buildCreateSlice({ creators }?: BuildCreateSliceConfig): <State, CaseReducers extends SliceCaseReducers<State>, Name extends string, Selectors extends SliceSelectors<State>, ReducerPath extends string = Name>(options: CreateSliceOptions<State, CaseReducers, Name, ReducerPath, Selectors>) => Slice<State, CaseReducers, Name, ReducerPath, Selectors>;
- /**
- * A function that accepts an initial state, an object full of reducer
- * functions, and a "slice name", and automatically generates
- * action creators and action types that correspond to the
- * reducers and state.
- *
- * @public
- */
- export declare const createSlice: <State, CaseReducers extends SliceCaseReducers<State>, Name extends string, Selectors extends SliceSelectors<State>, ReducerPath extends string = Name>(options: CreateSliceOptions<State, CaseReducers, Name, ReducerPath, Selectors>) => Slice<State, CaseReducers, Name, ReducerPath, Selectors>;
- export {};
|