export interface SubscriptionCallback { (item: T): void; } // eslint-disable-next-line @typescript-eslint/ban-types export interface Store { subscribeToItem( key: K, callback: SubscriptionCallback ): void; unsubscribeFromItem( key: K, callback: SubscriptionCallback ): void; updateItem(key: K, item: T[K]): void; getItem(key: K): T[K]; } // eslint-disable-next-line @typescript-eslint/ban-types export function createStore( initialState: T = {} as T ): Store { let state: T = initialState; const listeners: { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x in keyof T]: Array<(v: any) => void>; } = {} as { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x in keyof T]: Array<(v: any) => void>; }; return { subscribeToItem(key, callback) { listeners[key] = listeners[key] || []; listeners[key]!.push(callback); }, unsubscribeFromItem(key, callback) { const listener = listeners[key]; if (listener) { listeners[key] = listener.filter( (currentListener) => currentListener !== callback ); } }, updateItem(key, item) { state = { ...state, [key]: item, }; const listener = listeners[key]; if (listener) { listener.forEach((currentListener) => currentListener(state[key])); } }, getItem(key) { return state[key]; }, }; }