import type { SliceConfig } from './create-slice.js'; type InferState = Configs extends [ SliceConfig, ...infer Rest, ] ? { [name in Name]: Value } & { [actionName in keyof Actions]: ( ...args: Parameters ) => void; } & InferState : unknown; type HasDuplicatedNames = Configs extends [ SliceConfig, ...infer Rest, ] ? Extract extends never ? HasDuplicatedNames : true : false; type ValidConfigs = HasDuplicatedNames extends true ? never : Configs; type SetState = (fn: (state: T) => Partial) => void; type GetState = () => T; export function withSlices< Configs extends SliceConfig>[], >( ...configs: ValidConfigs ): ( set: SetState>, get: GetState>, ) => InferState { return (set) => { const state: Record = {}; type ActionFn = (...args: unknown[]) => (prev: unknown) => unknown; for (const config of configs) { state[config.name] = config.value; for (const [actionName, actionFn] of Object.entries( config.actions, )) { state[actionName] = (...args: unknown[]) => { set(((prevState: Record) => { const prevSlice = prevState[config.name]; const nextSlice = actionFn(...args)(prevSlice); if (Object.is(prevSlice, nextSlice)) { return prevState; } return { [config.name]: nextSlice }; }) as never); }; } } return state as never; }; }