type InferStateActions = Actions extends { [actionName: string]: (...args: never[]) => unknown; } ? { [actionName in keyof Actions]: ( ...args: Parameters ) => void; } : unknown; type IsValidActions = Extract extends never ? Actions : never; type SetState = (fn: (state: T) => Partial) => void; type GetState = () => T; export function withActions< State, Actions extends { [actionName: string]: (...args: never[]) => (state: State) => void; }, >( config: (set: SetState, get: GetState) => State, actions: IsValidActions, ): ( set: SetState>, get: GetState>, ) => State & InferStateActions { return (set, get) => { const state: Record = config(set as never, get) as never; for (const [actionName, actionFn] of Object.entries(actions)) { state[actionName] = (...args: unknown[]) => { actionFn(...(args as never[]))(get()); }; } return state as never; }; }