type ChangeFn = () => void type UnsubscribeFn = () => void type ActionFn = (this: T, ...args: any[]) => T | void type StoreActions = Record> export interface Store { getSnapshot(): T subscribe(onChange: ChangeFn): UnsubscribeFn dispatch(action: ActionKey, ...args: any[]): void } export function createStore( initial: () => T, actions: StoreActions ): Store { let state: T = initial() let listeners = new Set() return { getSnapshot() { return state }, subscribe(onChange) { listeners.add(onChange) return () => listeners.delete(onChange) }, dispatch(key: ActionKey, ...args: any[]) { let newState = actions[key].call(state, ...args) if (newState) { state = newState listeners.forEach((listener) => listener()) } }, } }