@propero/easy-store
Version:
Simple, intuitive, functional reactive stores for typescript
121 lines (112 loc) • 5.16 kB
TypeScript
type ArrayOr<T> = T | T[];
type PromiseOr<T> = T | Promise<T>;
type Subscriber<T extends unknown[]> = (...params: T) => void;
type SubscribeFunction<T extends unknown[]> = (listeners: ArrayOr<Subscriber<T>>) => () => void;
type NotifyFunction<T extends unknown[]> = (...value: T) => void;
interface SubscribableOptions {
maxListeners?: number;
}
interface Subscribable<T extends unknown[]> {
subscribe: SubscribeFunction<T>;
}
interface Notifiable<T extends unknown[]> {
notify: NotifyFunction<T>;
}
interface StoreOptions extends SubscribableOptions {
immediatelyNotify?: boolean;
}
interface StoreMethods<T> {
get(): T;
set(value: T): void;
set(updater: UpdateFunction<T>): Promise<void>;
patch(value: Partial<T>): void;
patch(patcher: PatchFunction<T>): Promise<void>;
}
type UpdateFunction<T> = (value: T) => PromiseOr<T>;
type PatchFunction<T> = (value: T) => PromiseOr<Partial<T>>;
type StoreSubscriber<T> = (newValue: T, oldValue?: T) => void;
type StoreSubscribeFunction<T> = SubscribeFunction<[
newValue: T,
oldValue?: T
]>;
type StoreGetter<T> = StoreMethods<T>["get"];
type StoreSetter<T> = StoreMethods<T>["set"];
type StorePatcher<T> = StoreMethods<T>["patch"];
interface Destroyable {
destroy(): void;
}
interface ReadonlyStore<T> {
get: StoreGetter<T>;
subscribe: StoreSubscribeFunction<T>;
}
interface PatchableStore<T> {
patch: StorePatcher<T>;
}
interface WritableStore<T> {
set: StoreSetter<T>;
}
interface AccessibleStore<T> {
get value(): T;
set value(val: T);
}
type StoreValues<T extends ReadonlyStore<any>[] | ReadonlyArray<ReadonlyStore<any>>> = T extends [ReadonlyStore<infer T0>] ? [T0] : T extends [ReadonlyStore<infer T0>, ReadonlyStore<infer T1>] ? [T0, T1] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>
] ? [T0, T1, T2] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>
] ? [T0, T1, T2, T3] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>,
ReadonlyStore<infer T4>
] ? [T0, T1, T2, T3, T4] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>,
ReadonlyStore<infer T4>,
ReadonlyStore<infer T5>
] ? [T0, T1, T2, T3, T4, T5] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>,
ReadonlyStore<infer T4>,
ReadonlyStore<infer T5>,
ReadonlyStore<infer T6>
] ? [T0, T1, T2, T3, T4, T5, T6] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>,
ReadonlyStore<infer T4>,
ReadonlyStore<infer T5>,
ReadonlyStore<infer T6>,
ReadonlyStore<infer T7>
] ? [T0, T1, T2, T3, T4, T5, T6, T7] : T extends [
ReadonlyStore<infer T0>,
ReadonlyStore<infer T1>,
ReadonlyStore<infer T2>,
ReadonlyStore<infer T3>,
ReadonlyStore<infer T4>,
ReadonlyStore<infer T5>,
ReadonlyStore<infer T6>,
ReadonlyStore<infer T7>,
ReadonlyStore<infer T8>
] ? [T0, T1, T2, T3, T4, T5, T6, T7, T8] : {
[Key in keyof T]: T[Key] extends ReadonlyStore<infer V> ? V : never;
};
declare function createAccessors<T, Val>(obj: Val, get: StoreGetter<T>, set: StoreSetter<T>): Val & AccessibleStore<T>;
declare function createGetSet<T>(initial: T, notify: NotifyFunction<[newVal: T, oldVal?: T]>): [get: StoreGetter<T>, set: StoreSetter<T>];
declare function createPatch<T>(get: StoreGetter<T>, set: StoreSetter<T>): StorePatcher<T>;
declare function createStoreSubscribe<T>(sub: SubscribeFunction<[newValue: T, oldValue?: T]>, get: StoreGetter<T>, immediatelyNotify?: boolean): SubscribeFunction<[newValue: T, oldValue?: T]>;
declare function createStore<T>(initialValue: T, { maxListeners, immediatelyNotify }?: StoreOptions): ReadonlyStore<T> & PatchableStore<T> & WritableStore<T> & AccessibleStore<T>;
declare function createSubscribable<T extends unknown[]>({ maxListeners, }?: SubscribableOptions): Subscribable<T> & Notifiable<T>;
declare function deriveStore<T extends ReadonlyStore<any>[] | ReadonlyArray<ReadonlyStore<any>>, R>(stores: T, handler: (...values: StoreValues<T>) => R, initial?: R, options?: StoreOptions): ReadonlyStore<R> & Destroyable;
declare function deriveStore<T extends ReadonlyStore<any>[] | ReadonlyArray<ReadonlyStore<any>>, R>(stores: T, handler: (...values: StoreValues<T>) => Promise<R>, initial: R, options?: StoreOptions): ReadonlyStore<R> & Destroyable;
export { AccessibleStore, ArrayOr, Destroyable, Notifiable, NotifyFunction, PatchFunction, PatchableStore, PromiseOr, ReadonlyStore, StoreGetter, StoreMethods, StoreOptions, StorePatcher, StoreSetter, StoreSubscribeFunction, StoreSubscriber, StoreValues, Subscribable, SubscribableOptions, SubscribeFunction, Subscriber, UpdateFunction, WritableStore, createAccessors, createGetSet, createPatch, createStore, createStoreSubscribe, createSubscribable, createStore as default, deriveStore };