diff --git a/src/store.ts b/src/store.ts index 1f00503af2..ef86130f56 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,32 +1,64 @@ import { run_all, noop, safe_not_equal, is_function } from './internal/utils'; +/** Callback to inform of a value updates. */ type Subscriber = (value: T) => void; +/** Unsubscribes from value updates. */ type Unsubscriber = () => void; +/** Callback to update a value. */ type Updater = (value: T) => T; +/** Cleanup logic callback. */ type Invalidater = (value?: T) => void; +/** Start and stop notification callbacks. */ type StartStopNotifier = (set: Subscriber) => Unsubscriber | void; +/** Readable interface for subscribing. */ export interface Readable { + /** + * Subscribe on value changes. + * @param run subscription callback + * @param invalidate cleanup callback + */ subscribe(run: Subscriber, invalidate?: Invalidater): Unsubscriber; } +/** Writable interface for both updating and subscribing. */ export interface Writable extends Readable { + /** + * Set value and inform subscribers. + * @param value to set + */ set(value: T): void; + + /** + * Update value using callback and inform subscribers. + * @param updater callback + */ update(updater: Updater): void; } +/** Pair of subscriber and invalidator. */ type SubscribeInvalidateTuple = [Subscriber, Invalidater]; +/** + * Creates a `Readable` store that allows reading by subscription. + * @param value initial value + * @param start start and stop notifications for subscriptions + */ export function readable(value: T, start: StartStopNotifier): Readable { return { subscribe: writable(value, start).subscribe, }; } +/** + * Create a `Writable` store that allows both updating and reading by subscription. + * @param value initial value + * @param start start and stop notifications for subscriptions + */ export function writable(value: T, start: StartStopNotifier = noop): Writable { let stop: Unsubscriber; const subscribers: Array> = []; @@ -68,11 +100,20 @@ export function writable(value: T, start: StartStopNotifier = noop): Writa return { set, update, subscribe }; } +/** One or more `Readable`s. */ type Stores = Readable | [Readable, ...Array>]; +/** One or more values from `Readable` stores. */ type StoresValues = T extends Readable ? U : { [K in keyof T]: T[K] extends Readable ? U : never }; +/** + * Derived value store by synchronizing one or more readable stores and + * applying an aggration function over its input values. + * @param stores input stores + * @param fn function callback that aggregates the values + * @param initial_value when used asynchronously + */ export function derived( stores: S, fn: (values: StoresValues, set?: Subscriber) => T | Unsubscriber | void, @@ -129,6 +170,10 @@ export function derived( }); } +/** + * Get the current value from a store by subscribing and immediately unsubscribing. + * @param store readable + */ export function get(store: Readable): T { let value: T | undefined; store.subscribe((_: T) => value = _)();