import { produce } from 'immer'; import type { Draft } from 'immer'; // Utility type to infer the argument types of the actions type InferArgs = T extends (...args: infer A) => unknown ? A : never; type SliceActions = { [actionName: string]: ( ...args: never[] ) => (draft: Draft) => Draft | void; }; export type SliceConfig< Name extends string, Value, Actions extends SliceActions, > = { name: Name; value: Value; actions: Actions; }; type ImmerActions> = { [K in keyof Actions]: ( ...args: InferArgs ) => (prev: Value) => Value; }; export function createSliceWithImmer< Name extends string, Value, Actions extends SliceActions, >(config: SliceConfig) { const immerActions = Object.fromEntries( Object.entries(config.actions).map(([actionKey, action]) => [ actionKey, (...args: InferArgs) => (prev: Value) => produce(prev, (draft) => action(...args)(draft)), ]), ) as unknown as ImmerActions; return { ...config, actions: immerActions, }; }