import type { Draft } from 'immer';
import type { TypeGuard } from './types/ts-helpers';
import type { Action, ActionType, AnyAction, ExtractAction } from './types/actions';
import type { ReducerWithInitialState } from './types/reducers';
type NotFunction<T = unknown> = T extends Function ? never : T;
export type ActionMatcherDescription<S, A extends AnyAction> = {
    matcher: TypeGuard<A> | ((action: A) => boolean);
    reducer: CaseReducer<S, NoInfer<A>>;
};
type ActionMatcherDescriptionCollection<S> = Array<ActionMatcherDescription<S, any>>;
interface TypedActionCreator<Type extends string> {
    (...args: any[]): Action<Type>;
    type: Type;
}
type CaseReducer<S = unknown, A extends Action = AnyAction> = (state: Draft<S>, action: A) => S | void | Draft<S>;
type CaseReducers<S, AS extends Record<string, Action>> = {
    [T in keyof AS]: AS[T] extends Action ? CaseReducer<S, AS[T]> : void;
};
/**
 * A utility function that allows defining a reducer as a mapping from action
 * type to *case reducer* functions that handle these action types. The
 * reducer's initial state is passed as the first argument.
 *
 * @remarks
 * The body of every case reducer is implicitly wrapped with a call to
 * `produce()` from the [immer](https://github.com/mweststrate/immer) library.
 * This means that rather than returning a new state object, you can also
 * mutate the passed-in state object directly; these mutations will then be
 * automatically and efficiently translated into copies, giving you both
 * convenience and immutability.
 *
 * @overloadSummary
 * This overload accepts a callback function that receives a `builder` object as its argument.
 * That builder provides `addCase`, `addMatcher` and `addDefaultCase` functions that may be
 * called to define what actions this reducer will handle.
 *
 * @param initialState - `State | (() => State)`: 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`.
 * @param builderCallback - `(builder: Builder) => void` A callback that receives a *builder* object to define
 *   case reducers via calls to `builder.addCase(actionCreatorOrType, reducer)`.
 *
 * @public
 */
export declare function createReducer<S extends NotFunction, A extends Action = AnyAction>(initialState: S | (() => S), builderCallback: (builder: ActionReducerMapBuilder<S, A>) => void): ReducerWithInitialState<S, A>;
/**
 * A builder for an action <-> reducer map.
 *
 * @public
 */
export interface ActionReducerMapBuilder<State, Actions extends AnyAction = AnyAction> {
    /**
     * Adds a case reducer to handle a single exact action type.
     * @remarks
     * All calls to `builder.addCase` must come before any calls to `builder.addMatcher` or `builder.addDefaultCase`.
     * @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.
     * @param reducer - The actual case reducer function.
     */
    addCase<ActionCreator extends TypedActionCreator<ActionType<Actions>>>(actionCreator: ActionCreator, reducer: CaseReducer<State, ReturnType<ActionCreator>>): ActionReducerMapBuilder<State, Actions>;
    /**
     * Adds a case reducer to handle a single exact action type.
     * @remarks
     * All calls to `builder.addCase` must come before any calls to `builder.addMatcher` or `builder.addDefaultCase`.
     * @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.
     * @param reducer - The actual case reducer function.
     */
    addCase<Type extends Actions['type']>(type: Type, reducer: CaseReducer<State, ExtractAction<Actions, Type>>): ActionReducerMapBuilder<State, Actions>;
    /**
     * Allows you to match your incoming actions against your own filter function instead of only the `action.type` property.
     * @remarks
     * If multiple matcher reducers match, all of them will be executed in the order
     * they were defined in - even if a case reducer already matched.
     * All calls to `builder.addMatcher` must come after any calls to `builder.addCase` and before any calls to `builder.addDefaultCase`.
     * @param matcher - A matcher function. In TypeScript, this should be a [type predicate](https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates)
     *   function
     * @param reducer - The actual case reducer function.
     *
     */
    addMatcher<TAction extends Actions = Actions>(matcher: (action: Actions) => action is TAction, reducer: CaseReducer<State, TAction extends AnyAction ? TAction : TAction & AnyAction>): Omit<ActionReducerMapBuilder<State, Actions>, 'addCase'>;
    addMatcher<TAction extends Actions = Actions>(matcher: (action: Actions) => boolean, reducer: CaseReducer<State, TAction extends AnyAction ? TAction : TAction & AnyAction>): Omit<ActionReducerMapBuilder<State, Actions>, 'addCase'>;
    /**
     * Adds a "default case" reducer that is executed if no case reducer and no matcher
     * reducer was executed for this action.
     * @param reducer - The fallback "default case" reducer function.
     */
    addDefaultCase(reducer: CaseReducer<State, AnyAction>): void;
}
export declare function executeReducerBuilderCallback<TState, TAction extends AnyAction>(builderCallback: (builder: ActionReducerMapBuilder<TState, TAction>) => void): [
    CaseReducers<TState, Record<string, TAction>>,
    ActionMatcherDescriptionCollection<TState>,
    CaseReducer<TState, TAction> | undefined
];
export {};
