/** * This tuple type is intended for use as a generic constraint to infer concrete * tuple type of ANY length. * * @see https://github.com/krzkaczor/ts-essentials/blob/a4c2485bc3f37843267820ec552aa662251767bc/lib/types.ts#L169 */ type Tuple = [T?, ...T[]] type RoTuple = readonly [T?, ...T[]] /** * Non inferential type parameter usage. NoInfer in source and in return of fn helps with detecting loose objects against target type. * * @see https://github.com/microsoft/TypeScript/issues/14829#issuecomment-504042546 */ type NoInfer = [T][T extends any ? 0 : never] /** * Generic Json type */ type Json = | null | undefined | boolean | string | number | Json[] | {[k: string]: Json} // Type for extention purpose. Represents combinable sample source. export type Combinable = {[key: string]: Store} | Tuple> // Helper type, which unwraps combinable sample source value. export type GetCombinedValue = Show<{ [K in keyof T]: T[K] extends Store ? U : never }> export type StoreValue = T extends Store ? S : never export type EventPayload = T extends Event ? P : never export type UnitValue = T extends Unit ? V : never export type EffectParams> = FX extends Effect< infer P, any, any > ? P : never export type EffectResult> = FX extends Effect< any, infer D, any > ? D : never export type EffectError> = FX extends Effect< any, any, infer E > ? E : never // Taken from the source code of typescript 4.5. Remove when we separate types for different versions /** * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`. */ type Awaited = T extends null | undefined ? T // special case for `null | undefined` when not in `--strictNullChecks` mode : T extends object // `await` only unwraps object types with a callable then. Non-object types are not unwrapped. ? T extends {then(onfulfilled: infer F): any} // thenable, extracts the first argument to `then()` ? F extends (value: infer V) => any // if the argument to `then` is callable, extracts the argument ? Awaited // recursively unwrap the value : never // the argument to `then` was not callable. : T // argument was not an object : T // non-thenable type OptionalParams = Args['length'] extends 0 // does handler accept 0 arguments? ? void // works since TS v3.3.3 : 0 | 1 extends Args['length'] // is the first argument optional? /** * Applying `infer` to a variadic arguments here we'll get `Args` of * shape `[T]` or `[T?]`, where T(?) is a type of handler `params`. * In case T is optional we get `T | undefined` back from `Args[0]`. * We lose information about argument's optionality, but we can make it * optional again by appending `void` type, so the result type will be * `T | undefined | void`. * * The disadvantage of this method is that we can't restore optonality * in case of `params?: any` because in a union `any` type absorbs any * other type (`any | undefined | void` becomes just `any`). And we * have similar situation also with the `unknown` type. */ ? Args[0] | void : Args[0] type EffectByHandler = FN extends (...args: infer Args) => infer Done ? Effect, Awaited, Fail> : never export const version: string export type kind = 'store' | 'event' | 'effect' | 'domain' | 'scope' export type Observer = { readonly next?: (value: A) => void //error(err: Error): void //complete(): void } export type Observable = { subscribe: (observer: Observer) => Subscription } export type Subscription = { (): void unsubscribe(): void } export interface Unit { readonly kind: kind readonly __: T } export interface UnitTargetable extends Unit { readonly targetable: true } export type CompositeName = { shortName: string fullName: string path: Array } /** * This is a workaround for https://github.com/microsoft/TypeScript/issues/35162 * * The problem was that we couldn't use guard as sample's clock parameter because * sample's clock-related generic inferred as `unknown` in cases when guard returned * `Event`. This happens because `Event` has a callable signature. With `Unit` * as the return type we won't see any problems. */ type EventAsReturnType = any extends Payload ? Event : never type EventCallableAsReturnType = any extends Payload ? EventCallable : never /** * Event you can subscribe to. * It represents a user action, a step in the application process, a command to execute, or an intention to make modifications, among other things. */ export interface Event extends Unit { kind: "event" map(fn: (payload: Payload) => T): EventAsReturnType filter(config: { fn(payload: Payload): payload is T }): EventAsReturnType filter(config: {fn(payload: Payload): boolean}): EventAsReturnType filterMap(fn: (payload: Payload) => T | undefined): EventAsReturnType watch(watcher: (payload: Payload) => any): Subscription subscribe(observer: Observer): Subscription /** * @deprecated use .compositeName.fullName instead */ getType(): string compositeName: CompositeName sid: string | null shortName: string } /** * The function you can call to trigger an event. */ export interface EventCallable extends Event, UnitTargetable { kind: "event" (payload: Payload): Payload (this: IfUnknown, payload?: Payload): void prepend(fn: (_: Before) => Payload): EventCallable } /** * Container for (possibly async) side effects */ export interface Effect extends UnitTargetable { kind: "effect" (params: Params): Promise readonly done: Event<{params: Params; result: Done}> readonly doneData: Event readonly fail: Event<{params: Params; error: Fail}> readonly failData: Event readonly finally: Event< | { status: 'done' params: Params result: Done } | { status: 'fail' params: Params error: Fail } > readonly use: { (handler: (params: Params) => Promise | Done): Effect< Params, Done, Fail > getCurrent(): (params: Params) => Promise } pending: Store inFlight: Store watch(watcher: (payload: Params) => any): Subscription filter(config: { fn(payload: Params): payload is T }): EventAsReturnType filter(config: {fn(payload: Params): boolean}): EventAsReturnType filterMap(fn: (payload: Params) => T | undefined): EventAsReturnType map(fn: (params: Params) => T): EventAsReturnType prepend(fn: (_: Before) => Params): EventCallable subscribe(observer: Observer): Subscription getType(): string compositeName: CompositeName sid: string | null shortName: string } type InferValueFromTupleOfUnits>> = T[number] extends Unit ? R : never type InferValueFromTupleOfUnitTargetables>> = T[number] extends UnitTargetable? R : never export interface Store extends Unit { kind: "store" map(fn: (state: State) => T, config?: {skipVoid?: boolean}): Store updates: Event getState(): State subscribe(listener: Observer | ((state: State) => any)): Subscription watch(watcher: (state: State, payload: undefined) => any): Subscription watch( trigger: Unit, watcher: (state: State, payload: E) => any, ): Subscription /** * @deprecated use js pipe instead */ thru(fn: (store: Store) => U): U defaultState: State compositeName: CompositeName shortName: string sid: string | null } /** * Hacky way to force TS perform checks against unsafe widening */ interface StoreValueType { _: X (type: X): void } export interface StoreWritable extends Store, UnitTargetable { kind: "store" readonly ____: StoreValueType on( trigger: Unit, reducer: (state: State, payload: E) => State | void, ): this on( triggers: Unit[], reducer: (state: State, payload: E) => State | void, ): this on>>( triggers: E, reducer: (state: State, payload: InferValueFromTupleOfUnits) => State | void, ): this off(trigger: Unit): this reset(...triggers: Array>): this reset(triggers: Array>): this reinit: EventCallable } interface InternalStore extends StoreWritable { setState(state: State): void } export const is: { unit(obj: unknown): obj is Unit | UnitTargetable store( obj: O | Unit | UnitTargetable, ): obj is typeof obj extends Unit ? Store | StoreWritable : Store | StoreWritable event( obj: O | Unit | UnitTargetable ): obj is typeof obj extends Unit ? Event | EventCallable : Event | EventCallable effect( obj: O | Effect ): obj is Effect domain(obj: unknown): obj is Domain scope(obj: unknown): obj is Scope attached>(obj: unknown): obj is E targetable(obj: Unit): obj is UnitTargetable } /** * A way to group and process events, stores and effects. Useful for logging and assigning a reset trigger to many effects. * Domain is notified via onCreateEvent, onCreateStore, onCreateEffect, onCreateDomain methods when events, stores, effects, or nested domains are created */ export class Domain implements Unit { readonly kind: kind readonly __: any onCreateEvent(hook: (newEvent: EventCallable) => any): Subscription onCreateEffect( hook: (newEffect: Effect) => any, ): Subscription onCreateStore( hook: (newStore: InternalStore) => any, ): Subscription onCreateDomain(hook: (newDomain: Domain) => any): Subscription event(name?: string): EventCallable event(config: {name?: string; sid?: string}): EventCallable createEvent(name?: string): EventCallable createEvent(config: { name?: string sid?: string }): EventCallable effect(handler: FN): EffectByHandler effect( handler: (params: Params) => Done | Promise, ): Effect effect(handler: FN): EffectByHandler effect( name?: string, config?: { handler?: (params: Params) => Promise | Done sid?: string }, ): Effect effect(config: { handler?: (params: Params) => Promise | Done sid?: string name?: string }): Effect createEffect(handler: FN): EffectByHandler createEffect( handler: (params: Params) => Done | Promise, ): Effect createEffect(handler: FN): EffectByHandler createEffect(config: { name?: string handler: FN sid?: string }): EffectByHandler createEffect( name?: string, config?: { handler?: (params: Params) => Promise | Done sid?: string }, ): Effect createEffect(config: { handler?: (params: Params) => Promise | Done sid?: string name?: string }): Effect domain(name?: string): Domain createDomain(name?: string): Domain store( defaultState: State, config?: { name?: string sid?: string updateFilter?: (update: State, current: State) => boolean serialize?: | 'ignore' | { write: (state: State) => SerializedState read: (json: SerializedState) => State } }, ): StoreWritable createStore( defaultState: State, config?: { name?: string sid?: string updateFilter?: (update: State, current: State) => boolean serialize?: | 'ignore' | { write: (state: State) => SerializedState read: (json: SerializedState) => State } skipVoid?: boolean }, ): StoreWritable sid: string | null compositeName: CompositeName shortName: string getType(): string history: { domains: Set stores: Set> effects: Set> events: Set> } } export type ID = string export type StateRefOp = | {type: 'map'; from?: StateRef; fn?: (value: any) => any} | {type: 'field'; from: StateRef; field: string} export type StateRef = { id: ID current: any type?: 'list' | 'shape' before?: StateRefOp[] noInit?: boolean sid?: string } export type Stack = { value: any a: any b: any parent?: Stack node: Node page?: any scope?: Scope meta?: Record } type BarrierPriorityTag = 'barrier' | 'sampler' | 'effect' type FromValue = { from: 'value' store: any } type FromStore = { from: 'store' store: StateRef } type FromRegister = { from: 'a' | 'b' | 'stack' } type ToRegister = { to: 'a' | 'b' | 'stack' } type ToStore = { to: 'store' target: StateRef } type MoveCmd = { id: ID type: 'mov' data: Data order?: { priority: BarrierPriorityTag barrierID?: number } } export type Cmd = | Compute | Mov type MovValReg = MoveCmd type MovValStore = MoveCmd type MovStoreReg = MoveCmd type MovStoreStore = MoveCmd type MovRegReg = MoveCmd type MovRegStore = MoveCmd export type Mov = | MovValReg | MovValStore | MovStoreReg | MovStoreStore | MovRegReg | MovRegStore export type Compute = { id: ID type: 'compute' data: { fn?: (data: any, scope: {[key: string]: any}, reg: Stack) => any safe: boolean filter: boolean pure: boolean } order?: { priority: BarrierPriorityTag barrierID?: number } } export type Node = { id: ID next: Array seq: Array scope: {[field: string]: any} meta: {[field: string]: any} family: { type: 'regular' | 'crosslink' | 'domain' links: Node[] owners: Node[] } } export const step: { compute(data: { fn?: (data: any, scope: {[key: string]: any}, stack: Stack) => any batch?: boolean priority?: BarrierPriorityTag | false safe?: boolean filter?: boolean pure?: boolean }): Compute filter(data: { fn: (data: any, scope: {[field: string]: any}, stack: Stack) => boolean pure?: boolean }): Compute run(data: {fn: (data: any, scope: {[field: string]: any}, stack: Stack) => any}): Compute mov(data: { from?: 'value' | 'store' | 'stack' | 'a' | 'b' to?: 'stack' | 'a' | 'b' | 'store' store?: StateRef target?: StateRef batch?: boolean priority?: BarrierPriorityTag | false }): Mov } /* `forward` types */ type ForwardTarget = UnitTargetable | ReadonlyArray> type CleanSingleTarget< Target extends UnitTargetable, Clock, > = Target extends UnitTargetable ? T extends void ? UnitTargetable : T extends Clock ? UnitTargetable // Needed to force typecheck : UnitTargetable : never type CleanTarget< Target extends ForwardTarget, From, > = Target extends UnitTargetable ? CleanSingleTarget : { [K in keyof Target]: Target[K] extends UnitTargetable ? CleanSingleTarget : never } /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { /** * By default TS picks "best common type" `T` between `from` and `to` arguments. * This lets us forward from `string | number` to `string` for instance, and * this is wrong. * * Fortunately we have a way to disable such behavior. By adding `& {}` to some * generic type we tell TS "do not try to infer this generic type from * corresponding argument type". * * Generic `T` won't be inferred from `from` any more. Forwarding from "less * strict" to "more strict" will produce an error as expected. * * @see https://www.typescriptlang.org/docs/handbook/type-inference.html#best-common-type */ from: Unit to: CleanTarget }): Subscription /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { from: Unit to: ReadonlyArray> }): Subscription /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { from: ReadonlyArray> to: ReadonlyArray> }): Subscription /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { from: ReadonlyArray> to: UnitTargetable }): Subscription /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { from: ReadonlyArray> to: UnitTargetable | ReadonlyArray> }): Subscription // Allow `* -> void` forwarding (e.g. `string -> void`). /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: {from: Unit; to: UnitTargetable}): Subscription // Do not remove the signature below to avoid breaking change! /** * Method to create connection between units in a declarative way. Sends updates from one set of units to another * @deprecated use `sample({clock, target})` instead */ export function forward(opts: { from: Unit to: UnitTargetable | ReadonlyArray> }): Subscription /** * Merges array of units (events, effects or stores), returns a new event, which fires upon trigger of any of given units * @param units array of units to be merged */ export function merge(units: ReadonlyArray>): EventAsReturnType /** * Merges array of units (events, effects or stores), returns a new event, which fires upon trigger of any of given units * @param units array of units to be merged */ export function merge>>( units: T, ): T[number] extends Unit ? Event : never /** * Method for destroying units and graph nodes. Low level tool, usually absent in common applications * @param unit unit to be erased * @param opts optional configuration object */ export function clearNode(unit: Unit | Node, opts?: {deep?: boolean}): void /** * Method to create a new graph node. Low level tool, usually absent in common applications */ export function createNode(opts?: { node?: Array parent?: Array | Node> child?: Array | Node> scope?: {[field: string]: any} meta?: {[field: string]: any} family?: { type?: 'regular' | 'crosslink' | 'domain' owners?: Unit | Node | Array | Node> links?: Unit | Node | Array | Node> } regional?: boolean }): Node /** * Allows to directly start computation from given unit or graph node. Low level tool, usually absent in common applications * @param unit unit or graph node to launch * @param payload data to pass to computation */ export function launch(unit: Unit | Node, payload: T): void /** * Allows to directly start computation from given unit or graph node. Low level tool, usually absent in common applications * @param config configuration object */ export function launch(config: { target: Unit | Node params: T defer?: boolean page?: any scope?: Scope meta?: Record }): void /** * Allows to directly start computation from given unit or graph node. Low level tool, usually absent in common applications * @param config configuration object */ export function launch(config: { target: Array | Node> params: any[] defer?: boolean page?: any scope?: Scope meta?: Record }): void /** * Method to create an event subscribed to given observable * @param observable object with `subscribe` method, e.g. rxjs stream or redux store */ export function fromObservable(observable: unknown): Event /** * Creates an event */ export function createEvent(eventName?: string): EventCallable /** * Creates an event */ export function createEvent(config: { name?: string sid?: string domain?: Domain }): EventCallable /** * Creates an effect * @param handler function to handle effect calls */ export function createEffect(handler: FN): EffectByHandler /** * Creates an effect * @param handler function to handle effect calls */ export function createEffect( handler: (params: Params) => Done | Promise, ): Effect /** * Creates an effect * @param handler function to handle effect calls */ export function createEffect(handler: FN): EffectByHandler /** * Creates an effect */ export function createEffect(name: string, config: { handler: FN sid?: string domain?: Domain }): EffectByHandler /** * Creates an effect */ export function createEffect( effectName?: string, config?: { handler?: (params: Params) => Promise | Done sid?: string domain?: Domain }, ): Effect /** * Creates an effect */ export function createEffect(config: { name?: string handler: FN sid?: string domain?: Domain }): EffectByHandler /** * Creates an effect */ export function createEffect(config: { name?: string handler?: (params: Params) => Promise | Done sid?: string domain?: Domain }): Effect /** * Creates a store * @param defaultState default state * @param config optional configuration object */ export function createStore( defaultState: State, config?: { skipVoid?: boolean; name?: string; sid?: string updateFilter?: (update: State, current: State) => boolean serialize?: | 'ignore' | { write: (state: State) => SerializedState read: (json: SerializedState) => State } domain?: Domain; }, ): StoreWritable export function setStoreName(store: Store, name: string): void type UnionToIntersection = ( Union extends any ? (k: Union) => void : never ) extends (k: infer intersection) => void ? intersection : never; type GetUnionLast = UnionToIntersection< Union extends any ? () => Union : never > extends () => infer Last ? Last : never; /** * Chooses one of the cases by given conditions. It "splits" source unit into several events, which fires when payload matches their conditions. * Works like pattern matching for payload values and external stores * @param source unit which will trigger computation in split * @param match object with matching functions which allows to trigger one of created events */ export function split< S, Match extends {[name: string]: (payload: S) => boolean} >( source: Unit, match: Match, ): Show<{ [K in keyof Match]: Match[K] extends (p: any) => p is infer R ? Event : Event } & {__: Event}> type MatchConstraint = Unit | ((p: UnitValue) => void) | Record) => boolean) | Store>; type CaseRecord = Partial | RoTuple>>>; /** * Chooses one of cases by given conditions. It "splits" source unit into several targets, which fires when payload matches their conditions. * Works like pattern matching for payload values and external units */ export function split< Clock extends Unit | RoTuple>, Source extends Unit, Match extends MatchConstraint, Cases extends CaseRecord>, >( config: SplitConfig ): void; type SplitConfig< Clock, Source, Match extends MatchConstraint, Cases extends CaseRecord> > = Exclude extends InferMatchKeys ? TypeOfMatch extends 'record' ? SplitImpl : TypeOfMatch extends 'unit' ? SplitImpl : TypeOfMatch extends 'fn' ? SplitImpl : {clock?: Clock; source: Source; match: Match; cases: Cases} : { clock?: Clock; source: Source; match: RebuildMatch; cases: { [K in keyof Cases as K extends InferMatchKeys | '__' ? K : never]: Cases[K] }; }; type InferMatchKeys = Match extends Unit ? Keys extends PropertyKey ? Keys : never : Match extends (source: any) => infer Keys ? Keys extends PropertyKey ? Keys : never : Match extends Record boolean) | Store> ? keyof Match : never; type TypeOfMatch = Match extends Unit ? 'unit' : Match extends (s: any) => void ? 'fn' : Match extends Record void) | Store> ? 'record' : never; type RebuildMatch< Source, Match, Cases, Keys extends PropertyKey = Exclude > = Match extends Unit ? Unit : Match extends (p: UnitValue) => void ? (p: UnitValue) => Keys : Match extends Record) => boolean) | Store> ? { [K in Keys]: K extends keyof Match ? Match[K] : (p: UnitValue) => boolean | Store } : never; type SplitImpl< Clock, Source, Match, Cases > = MatchCasesIsAssignable extends infer AssignableDict ? AssignableDict extends Record ? { clock?: Clock; source: Source; match: Match; cases: Cases } : MatchHasInference extends 'yes' ? { clock?: Clock; source: Source; match: RebuildMatchInference; cases: Show>; } : { clock?: Clock; source: RebuildSource; match: Match; cases: Show>; } : never; type MatchValueReader = K extends keyof Match ? Match[K] extends (src: any) => src is infer R ? UnitValue extends R ? UnitValue : R : UnitValue : UnitValue; type MatchHasInference = Match extends Record) => boolean) | Store> ? 'yes' extends { [K in keyof Match]: UnitValue extends MatchValueReader ? 'no' : 'yes' }[keyof Match] ? 'yes' : 'no' : 'no'; type MatchCasesIsAssignable< Source, Match, Cases > = { [K in keyof Cases]: IfCaseAssignableToValue> } type IfValidCaseValue = WhichType extends 'void' | 'unknown' ? Y : IfAssignable; type IfCaseAssignableToValue = Case extends UnitTargetable ? IfValidCaseValue, Value, 'yes', ['no', UnitValue]> : Case extends RoTuple> ? IsCaseAssignableToValueLoop : never; type IsCaseAssignableToValueLoop>, Value> = Cases extends readonly [infer Case, ...infer Rest] ? Rest extends readonly any[] ? IfValidCaseValue, Value, 'yes', 'no'> extends 'yes' ? IsCaseAssignableToValueLoop : ['no', UnitValue] : never : 'yes'; type RebuildMatchInference< Source, Match, AssignableDict > = Match extends Record) => boolean) | Store> ? { [K in keyof Match]: K extends keyof AssignableDict ? AssignableDict[K] extends ['no', infer Value] ? Value extends UnitValue ? (source: UnitValue) => source is Value : never : Match[K] : Match[K] } : never; type RebuildCases = { [K in keyof Cases]: K extends InferMatchKeys | '__' ? RebuildCase, Cases[K]> : Cases[K]; } type RebuildCase = Case extends UnitTargetable ? IfValidCaseValue> : Case extends RoTuple> ? RebuildCaseLoop : never; type RebuildCaseLoop = Cases extends readonly [infer Case, ...infer Rest] ? Rest extends readonly any[] ? RebuildCaseLoop< Rest, Value, [ ...Result, IfValidCaseValue, Value, Case, UnitTargetable> ] > : Result : Result; type RebuildSource = { [K in keyof Cases]: GetFirstUnassignableCase, Cases[K]> } extends infer Values ? Values extends Record ? Source : { [K in keyof Values as [Values[K]] extends [never] ? never : K]: Values[K] } extends infer InvalidValues ? Unit> : never : never; type GetFirstUnassignableCase = Case extends UnitTargetable ? IfValidCaseValue : Case extends RoTuple> ? GetFirstUnassignableLoop : never; type GetFirstUnassignableLoop>, Value> = Cases extends readonly [infer Case, ...infer Rest] ? Rest extends readonly any[] ? IfValidCaseValue, Value, 'yes', 'no'> extends 'yes' ? GetFirstUnassignableLoop : UnitValue : never : never; /** * Shorthand for creating events attached to store by providing object with reducers for them * @param store target store * @param api object with reducers */ export function createApi< S, Api extends {[name: string]: ((store: S, e: any) => (S | void))} >( store: StoreWritable, api: Api, ): { [K in keyof Api]: ((store: S, e: void) => (S | void)) extends Api[K] ? EventCallable : Api[K] extends ((store: S) => (S | void)) ? EventCallable : Api[K] extends ((store: S, e: infer E) => (S | void)) ? EventCallable | void : E> : any } /** * Creates a Store out of successful results of Effect. * It works like a shortcut for `createStore(defaultState).on(effect.done, (_, {result}) => result)` * @param effect source effect * @param defaultState initial state of new store */ export function restore( effect: Effect, defaultState: Done, ): StoreWritable /** * Creates a Store out of successful results of Effect. * It works like a shortcut for `createStore(defaultState).on(effect.done, (_, {result}) => result)` * @param effect source effect * @param defaultState initial state of new store */ export function restore( effect: Effect, defaultState: null, ): StoreWritable /** * Creates a Store from Event. * It works like a shortcut for `createStore(defaultState).on(event, (_, payload) => payload)` * @param event source event * @param defaultState initial state of new store */ export function restore(event: Event, defaultState: E): StoreWritable /** * Creates a Store from Event. * It works like a shortcut for `createStore(defaultState).on(event, (_, payload) => payload)` * @param event source event * @param defaultState initial state of new store */ export function restore(event: Event, defaultState: null): StoreWritable export function restore>(event: T): never export function restore>(effect: T): never export function restore | any}>( state: State, ): { [K in keyof State]: State[K] extends Store ? StoreWritable : StoreWritable } /** * Creates a domain */ export function createDomain(domainName?: string, config?: { domain?: Domain }): Domain export function createDomain(config?: { name?: string; domain?: Domain }): Domain type WhichTypeKind = | 'never' | 'any' | 'unknown' | 'void' | 'undefined' | 'value' type NotType = Exclude type WhichType = [T] extends [never] ? 'never' : [unknown] extends [T] ? [0] extends [1 & T] ? 'any' : 'unknown' : [T] extends [void] ? [void] extends [T] ? 'void' : 'undefined' : 'value' type BuiltInObject = | Error | Date | RegExp | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | ReadonlyMap | ReadonlySet | WeakMap | WeakSet | ArrayBuffer | DataView | Function | Promise | Generator type UnitObject = Store | Event | Effect | Unit /** * Force typescript to print real type instead of geneic types * * It's better to see {a: string; b: number} * instead of GetCombinedValue<{a: Store; b: Store}> * */ type Show = A extends BuiltInObject ? A : A extends UnitObject ? A : { [K in keyof A]: A[K] } // & {} /* sample types */ type TupleObject> = { [I in Exclude]: T[I] } type IfAny = 0 extends (1 & T) ? Y : N; type IfUnknown = 0 extends (1 & T) ? N : unknown extends T ? Y : N; type IfAssignable = (() => IfAny) extends (() => IfAny) ? Y : (T extends U ? never : 1) extends never ? Y : T extends Array ? number extends T['length'] ? N : U extends Array ? number extends U['length'] ? N : TupleObject extends TupleObject ? Y : N : N : N type Source = Unit | Combinable type Clock = Unit | Tuple> type Target = UnitTargetable | Tuple type GetTupleWithoutAny = T extends Array ? U extends Unit ? IfAny : never : never type GetMergedValue = GetTupleWithoutAny extends never ? any : GetTupleWithoutAny type GetSource = S extends Unit ? Value : GetCombinedValue type GetClock = C extends Unit ? Value : GetMergedValue /** Replaces incompatible unit type with string error message. * There is no error message if target type is void. */ type ReplaceUnit = IfAssignable // [...T] is used to show sample result as a tuple (not array) type TargetTuple, Result> = [...{ [Index in keyof Target]: Target[Index] extends UnitTargetable ? ReplaceUnit : 'non-unit item in target' }] type MultiTarget = Target extends UnitTargetable ? ReplaceUnit : Target extends Tuple ? TargetTuple : 'non-unit item in target' type SampleImpl< Target, Source, Clock, FLBool, FilterFun, FN, FNInf, FNInfSource extends ( Source extends Unit | SourceRecord ? TypeOfSource : never ), FNInfClock extends ( Clock extends Units ? TypeOfClock : never ), FNAltArg, FLUnit, SomeFN, > = // no target unknown extends Target // no target, no source ? unknown extends Source ? unknown extends Clock ? [message: {error: 'either target, clock or source should exists'}] // no target, no source, has clock : Clock extends Units ? SampleFilterDef< ModeSelector< 'clock | | filter | fn | ', 'clock | | filter | | ', 'clock | | | fn | ', 'clock | | | | ', SomeFN >, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] // no target, has source : Source extends Unit | SourceRecord // no target, has source, no clock ? unknown extends Clock ? SampleFilterDef< ModeSelector< ' | source | filter | fn | ', ' | source | filter | | ', ' | source | | fn | ', ' | source | | | ', SomeFN >, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > // no target, has source, has clock : Clock extends Units ? SampleFilterDef< ModeSelector< 'clock | source | filter | fn | ', 'clock | source | filter | | ', 'clock | source | | fn | ', 'clock | source | | | ', SomeFN >, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : [message: {error: 'source should be unit or object with stores'; got: Source}] // has target : Target extends UnitsTarget | ReadonlyArray> // has target, no source ? unknown extends Source ? unknown extends Clock ? [message: {error: 'either target, clock or source should exists'}] // has target, no source, has clock : Clock extends Units ? SampleFilterTargetDef< ModeSelector< 'clock | | filter | fn | target', 'clock | | filter | | target', 'clock | | | fn | target', 'clock | | | | target', SomeFN >, Target, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] // has target, has source : Source extends Unit | SourceRecord // has target, has source, no clock ? unknown extends Clock ? SampleFilterTargetDef< ModeSelector< ' | source | filter | fn | target', ' | source | filter | | target', ' | source | | fn | target', ' | source | | | target', SomeFN >, Target, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > // has target, has source, has clock : Clock extends Units ? SampleFilterTargetDef< ModeSelector< 'clock | source | filter | fn | target', 'clock | source | filter | | target', 'clock | source | | fn | target', 'clock | source | | | target', SomeFN >, Target, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource, FNInfClock, FNAltArg, SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : [message: {error: 'source should be unit or object with stores'; got: Source}] : Target extends InvalidUnitsTarget ? [message: {error: 'derived units are not allowed in target'; got: Target}] : [message: {error: 'target should be unit or array of units'; got: Target}] type ModeSelector< FilterAndFN, FilterOnly, FNOnly, None, SomeFN, > = unknown extends SomeFN ? FilterAndFN : SomeFN extends {fn: any; filter: any} ? FilterAndFN : SomeFN extends {filter: any} ? FilterOnly : SomeFN extends {fn: any} ? FNOnly : None type SampleRet< Target, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNAltArg, FNInf, FNInfSource extends ( Source extends Unit | SourceRecord ? TypeOfSource : never ), FNInfClock extends ( Clock extends Units ? TypeOfClock : never ), SomeFN, ForceTargetInference > = unknown extends Target ? unknown extends Clock ? unknown extends Source ? never : Source extends Unit | SourceRecord // has filter, has fn ? unknown extends SomeFN ? FLUnit extends Unit ? FN extends (src: TypeOfSource) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>) => any ? EventAsReturnType> : never : FilterFun extends (src: TypeOfSource) => src is FNInfSource ? FNInf extends (src: FNInfSource) => any ? EventAsReturnType> : never : FN extends (src: TypeOfSource) => any ? EventAsReturnType> : never // has filter, has fn : SomeFN extends {filter: any; fn: any} ? FLUnit extends Unit ? FN extends (src: TypeOfSource) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>) => any ? EventAsReturnType> : never : FilterFun extends (src: TypeOfSource) => src is FNInfSource ? FNInf extends (src: FNInfSource) => any ? EventAsReturnType> : never : FN extends (src: TypeOfSource) => any ? EventAsReturnType> : never // no filter, has fn : SomeFN extends {fn: any} ? FN extends (src: TypeOfSource) => any ? Source extends Store | SourceRecord ? Store> : EventAsReturnType> : never // has filter, no fn : SomeFN extends {filter: any} ? FLUnit extends Unit ? EventAsReturnType> : FLBool extends BooleanConstructor ? EventAsReturnType>> : FilterFun extends (src: TypeOfSource) => src is FNInfSource ? EventAsReturnType : EventAsReturnType> // no filter, no fn : Source extends Store | SourceRecord ? Store> : EventAsReturnType> : never : unknown extends Source ? Clock extends Units // has filter, has fn ? unknown extends SomeFN ? FLUnit extends Unit ? FN extends (clk: TypeOfClock) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>) => any ? EventAsReturnType> : never : FilterFun extends (clk: TypeOfClock) => clk is FNInfClock ? FNInf extends (clk: FNInfClock) => any ? EventAsReturnType> : never : FN extends (clk: TypeOfClock) => any ? EventAsReturnType> : never // has filter, has fn : SomeFN extends {filter: any; fn: any} ? FLUnit extends Unit ? FN extends (clk: TypeOfClock) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>) => any ? EventAsReturnType> : never : FilterFun extends (clk: TypeOfClock) => clk is FNInfClock ? FNInf extends (src: FNInfClock) => any ? EventAsReturnType> : never : FN extends (clk: TypeOfClock) => any ? EventAsReturnType> : never // no filter, has fn : SomeFN extends {fn: any} ? FN extends (clk: TypeOfClock) => any ? Clock extends Store ? Store> : EventAsReturnType> : never // has filter, no fn : SomeFN extends {filter: any} ? FLUnit extends Unit ? EventAsReturnType> : FLBool extends BooleanConstructor ? EventAsReturnType>> : FilterFun extends (clk: TypeOfClock) => clk is FNInfClock ? EventAsReturnType : EventAsReturnType> // no filter, no fn : Clock extends Store ? Store> : EventAsReturnType> : never : Clock extends Units ? Source extends Unit | SourceRecord // has filter, has fn ? unknown extends SomeFN ? FLUnit extends Unit ? FN extends (src: TypeOfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>, clk: TypeOfClock) => any ? EventAsReturnType> : never : FilterFun extends (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource ? FNInf extends (src: FNInfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never : FN extends (src: TypeOfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never // has filter, has fn : SomeFN extends {filter: any; fn: any} ? FLUnit extends Unit ? FN extends (src: TypeOfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never : FLBool extends BooleanConstructor ? FNAltArg extends (arg: NonFalsy>, clk: TypeOfClock) => any ? EventAsReturnType> : never : FilterFun extends (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource ? FNInf extends (src: FNInfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never : FN extends (src: TypeOfSource, clk: TypeOfClock) => any ? EventAsReturnType> : never // no filter, has fn : SomeFN extends {fn: any} ? FN extends (src: TypeOfSource, clk: TypeOfClock) => any ? [Clock, Source] extends [Store, Store | SourceRecord] ? Store> : EventAsReturnType> : never // has filter, no fn : SomeFN extends {filter: any} ? FLUnit extends Unit ? EventAsReturnType> : FLBool extends BooleanConstructor ? EventAsReturnType>> : FilterFun extends (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource ? EventAsReturnType : EventAsReturnType> // no filter, no fn : [Clock, Source] extends [Store, Store | SourceRecord] ? Store> : EventAsReturnType> : never : never : Target & ForceTargetInference /** * Represents a step in a business logic workflow. It tells an application when it should act, which data it needs, * how it should be transformed and what should happens next * * ```js * sample({ * // when clickBuy event is triggered * clock: clickBuy, * // read state of $shoppingCart store * source: $shoppingCart, * // and if there at least one item in cart * filter: (cart) => cart.items.length > 0, * // then select items from cart * fn: cart => cart.items, * // and pass results to buyItemsFx effect and clearCart event * target: [buyItemsFx, clearCart] * }) * ``` */ export function sample< Target, Source, Clock, FLBool, FNInfSource extends ( Source extends Unit | SourceRecord ? TypeOfSource : never ), FNInfClock extends ( Clock extends Units ? TypeOfClock : never ), FilterFun extends ( Source extends Unit | SourceRecord ? Clock extends Units ? ( | never | ((src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource) | ((src: TypeOfSource, clk: TypeOfClock) => boolean) ) : ( | never | ((src: TypeOfSource) => src is FNInfSource) | ((src: TypeOfSource) => boolean) ) : Clock extends Units ? ( | never | ((clk: TypeOfClock) => clk is FNInfClock) | ((clk: TypeOfClock) => boolean) ) : never ), FN extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => any : (src: TypeOfSource) => any : Clock extends Units ? (clk: TypeOfClock) => any : never ), FNInf extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: FNInfSource, clk: TypeOfClock) => any : (src: FNInfSource) => any : Clock extends Units ? (clk: FNInfClock) => any : never ), FNNonFalsy extends ( Source extends Unit | SourceRecord ? NonFalsy> : Clock extends Units ? NonFalsy> : never ), FNAltArg extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: FNNonFalsy, clk: TypeOfClock) => any : (src: FNNonFalsy) => any : Clock extends Units ? (clk: FNNonFalsy) => any : never ), SomeFN, SourceNoConf, ClockNoConf, FNSrcNoConf extends ( SourceNoConf extends Unit | SourceRecord ? (src: TypeOfSource) => any : never ), FNBothNoConf extends ( SourceNoConf extends Unit | SourceRecord ? ClockNoConf extends Units ? ((src: TypeOfSource, clk: TypeOfClock) => any) : never : never ), FLUnit, Args extends any[], InferTarget, >(...args: SourceNoConf extends Unit | SourceRecord ? ClockNoConf extends Units ? [any, any, any] extends Args ? [source: SourceNoConf, clock: ClockNoConf, fn: FNBothNoConf] & Args : [any, any] extends Args ? [source: SourceNoConf, clock: ClockNoConf] & Args : never : [any, any] extends Args ? [source: SourceNoConf, fn: FNSrcNoConf] & Args : Args extends [Unit] ? [source: SourceNoConf] & Args : SampleImpl : SampleImpl ): SourceNoConf extends Unit | SourceRecord ? ClockNoConf extends Units ? [any, any, any] extends Args ? SourceNoConf extends Store ? ClockNoConf extends Store ? Store> : EventAsReturnType> : EventAsReturnType> : [any, any] extends Args ? SourceNoConf extends Store ? ClockNoConf extends Store ? Store> : EventAsReturnType> : EventAsReturnType> : never : [any, any] extends Args ? SourceNoConf extends Store ? Store> : EventAsReturnType> : Args extends [Unit] ? SourceNoConf extends Store ? Store> : EventAsReturnType> : NoInfer> : NoInfer> /* | 'clock | source | filter | fn | target' | 'clock | source | | fn | target' | 'clock | source | filter | fn | ' | 'clock | source | | fn | ' | 'clock | source | filter | | target' | 'clock | source | | | target' | 'clock | source | filter | | ' | 'clock | source | | | ' | ' | source | filter | fn | target' | ' | source | | fn | target' | ' | source | filter | fn | ' | ' | source | | fn | ' | ' | source | filter | | target' | ' | source | | | target' | ' | source | filter | | ' | ' | source | | | ' | 'clock | | filter | fn | target' | 'clock | | | fn | target' | 'clock | | filter | fn | ' | 'clock | | | fn | ' | 'clock | | filter | | target' | 'clock | | | | target' | 'clock | | filter | | ' | 'clock | | | | ' */ type Mode_Clk_Src = `clock | source | ${string}`; type Mode_Clk_NoSrc = `clock | | ${string}`; type Mode_NoClk_Src = ` | source | ${string}`; type Mode_Trg = `${string} | target`; type Mode_Flt_Trg = `${string} | filter | ${string} | target`; type Mode_NoFlt = `${string} | ${string} | | ${string} | ${string}`; type Mode_Fn_Trg = `${string} | fn | target`; type Mode_Src = `${string} | source | ${string}`; type Mode_Flt_Fn_Trg = `${string} | filter | fn | target`; type Mode_Src_Flt_NoFn_Trg = `${string} | source | filter | | target`; type Mode_NoTrg = `${string} | `; type Mode_Flt = `${string} | filter | ${string}`; type Mode_Flt_Fn = `${string} | filter | fn | ${string}`; type TargetFilterFnConfig< Mode extends Mode_Flt_Trg, Target extends UnitsTarget | ReadonlyArray>, Source, Clock, FilterFun, FN, > = Mode extends 'clock | source | filter | fn | target' ? {clock: Clock; source: Source; filter?: FilterFun; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | filter | | target' ? {clock: Clock; source: Source; filter: FilterFun; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | target' ? {source: Source; clock?: never; filter?: FilterFun; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | target' ? {source: Source; clock?: never; filter: FilterFun; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | target' ? {clock: Clock; source?: never; filter?: FilterFun; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | target' ? {clock: Clock; source?: never; filter: FilterFun; target: Target; greedy?: boolean; batch?: boolean; name?: string} : never type TargetConfigCheck< Mode extends Mode_Trg, Target extends UnitsTarget | ReadonlyArray>, Source, Clock, FN, Config, SomeFN > = // mode with fn Mode extends Mode_Fn_Trg // there should be an explicit conditional selection // of generic variable for function type // this could be a reason for a few unfixed implicit any ? FN extends DataSourceFunction ? TargetOrError< ReturnType, 'fnRet', Target, Config & SomeFN > : [message: {error: 'function should accept data source types'; got: FN}] // mode with source only or with both clock and source : Mode extends Mode_Src ? Source extends Unit | SourceRecord ? TargetOrError< TypeOfSource, 'src', Target, Config & SomeFN > : [message: {error: 'source should be unit or object with stores'; got: Source}] // mode with clock only : Mode extends Mode_Clk_NoSrc ? Clock extends Units ? TargetOrError< TypeOfClock, 'clk', Target, Config & SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : never type InferredType = Source extends Unit | SourceRecord ? Clock extends Units ? FilterFN extends (src: any, clk: TypeOfClock) => src is infer Ret ? Ret extends TypeOfSource ? Ret : never : never : FilterFN extends (src: any) => src is infer Ret ? Ret extends TypeOfSource ? Ret : never : never : Clock extends Units ? FilterFN extends (clk: any) => clk is infer Ret ? Ret extends TypeOfClock ? Ret : never : never : never type SampleFilterTargetDef< Mode extends Mode_Trg, Target extends UnitsTarget | ReadonlyArray>, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource extends ( Source extends Unit | SourceRecord ? TypeOfSource : never ), FNInfClock extends ( Clock extends Units ? TypeOfClock : never ), FNAltArg, SomeFN > = Mode extends Mode_Flt_Trg ? FLUnit extends Unit ? boolean extends UnitValue ? FN extends DataSourceFunction ? TargetConfigCheck< Mode, Target, Source, Clock, FN, Mode extends 'clock | source | filter | fn | target' ? {clock: Clock; source: Source; filter?: FLUnit; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | filter | | target' ? {clock: Clock; source: Source; filter: FLUnit; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | target' ? {source: Source; clock?: never; filter?: FLUnit; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | target' ? {source: Source; clock?: never; filter: FLUnit; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | target' ? {clock: Clock; source?: never; filter?: FLUnit; fn?: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | target' ? {clock: Clock; source?: never; filter: FLUnit; target: Target; greedy?: boolean; batch?: boolean; name?: string} : never, SomeFN > : [message: {error: 'filter unit should has boolean type'; got: UnitValue}] : [message: {error: 'function should accept data source types'; got: FN}] : FLBool extends BooleanConstructor ? Mode extends Mode_Flt_Fn_Trg ? FNAltArg extends (arg?: any, clk?: any) => any ? TargetOrError< ReturnType, 'fnRet', Target, TargetFilterFnConfig & SomeFN > : never // mode with source only or with both clock and source : Mode extends Mode_Src_Flt_NoFn_Trg ? Source extends Unit | SourceRecord ? TargetOrError< NonFalsy>, 'src', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'source should be unit or object with stores'; got: Source}] // mode with clock only : Mode extends Mode_Clk_NoSrc ? Clock extends Units ? TargetOrError< NonFalsy>, 'clk', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : never : FilterFun extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource : (src: TypeOfSource) => src is FNInfSource : Clock extends Units ? (clk: TypeOfClock) => clk is FNInfClock : never ) // mode with fn ? Mode extends Mode_Flt_Fn_Trg ? FNInf extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: FNInfSource, clk: TypeOfClock) => any : (src: FNInfSource) => any : Clock extends Units ? (clk: FNInfClock) => any : any ) ? TargetOrError< ReturnType, 'fnRet', Target, TargetFilterFnConfig | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource : (src: TypeOfSource) => src is FNInfSource : Clock extends Units ? (clk: TypeOfClock) => clk is FNInfClock : never ), FNInf & ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: FNInfSource, clk: TypeOfClock) => any : (src: FNInfSource) => any : Clock extends Units ? (clk: FNInfClock) => any : any )> & SomeFN > : [message: {error: 'function should accept data source types'; got: FNInf}] // mode with source only or with both clock and source : Mode extends Mode_Src_Flt_NoFn_Trg ? Source extends Unit | SourceRecord ? TargetOrError< InferredType, 'src', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'source should be unit or object with stores'; got: Source}] // mode with clock only : Mode extends Mode_Clk_NoSrc ? Clock extends Units ? TargetOrError< InferredType, 'clk', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : never : FilterFun extends ( Mode extends Mode_Clk_Src ? Source extends Unit | SourceRecord ? Clock extends Units ? ((src: TypeOfSource, clk: TypeOfClock) => any) : never : never : Mode extends Mode_NoClk_Src ? Source extends Unit | SourceRecord ? (src: TypeOfSource) => any : never : Clock extends Units ? (clk: TypeOfClock) => any : never ) ? ReturnType extends boolean // mode with fn ? Mode extends Mode_Flt_Fn_Trg ? FN extends DataSourceFunction ? TargetOrError< ReturnType, 'fnRet', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'function should accept data source types'; got: FN}] // mode with source only or with both clock and source : Mode extends Mode_Src_Flt_NoFn_Trg ? Source extends Unit | SourceRecord ? TargetOrError< TypeOfSource, 'src', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'source should be unit or object with stores'; got: Source}] // mode with clock only : Mode extends Mode_Clk_NoSrc ? Clock extends Units ? TargetOrError< TypeOfClock, 'clk', Target, TargetFilterFnConfig & SomeFN > : [message: {error: 'clock should be unit or array of units'; got: Clock}] : never : [message: {error: 'filter function should return boolean'; got: ReturnType}] : [message: {error: 'filter should be function or unit'; got: FilterFun}] : Mode extends Mode_NoFlt ? FN extends DataSourceFunction ? TargetConfigCheck< Mode, Target, Source, Clock, FN, Mode extends 'clock | source | | fn | target' ? {clock: Clock; source: Source; filter?: never; fn: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | | | target' ? {clock: Clock; source: Source; filter?: never; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | | fn | target' ? {source: Source; clock?: never; filter?: never; fn: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | | | target' ? {source: Source; clock?: never; filter?: never; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | | fn | target' ? {clock: Clock; source?: never; filter?: never; fn: FN; target: Target; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | | | target' ? {clock: Clock; source?: never; filter?: never; target: Target; greedy?: boolean; batch?: boolean; name?: string} : never, SomeFN > : [message: {error: 'function should accept data source types'; got: FN}] : never type TargetOrError< MatchingValue, Mode extends 'fnRet' | 'src' | 'clk', Target extends UnitsTarget | ReadonlyArray>, ResultConfig > = [TypeOfTarget] extends [Target] ? [config: ResultConfig] : [Target] extends [TypeOfTargetSoft] ? [config: ResultConfig] : [message: { error: Mode extends 'fnRet' ? 'fn result should extend target type' : Mode extends 'src' ? 'source should extend target type' : 'clock should extend target type' targets: Show> }] type SampleFilterDef< Mode extends Mode_NoTrg, Source, Clock, FLUnit, FLBool, FilterFun, FN, FNInf, FNInfSource extends ( Source extends Unit | SourceRecord ? TypeOfSource : never ), FNInfClock extends ( Clock extends Units ? TypeOfClock : never ), FNAltArg, SomeFN > = Mode extends Mode_Flt ? FLUnit extends Unit ? boolean extends UnitValue ? [config: ( Mode extends 'clock | source | filter | fn | ' ? {clock: Clock; source: Source; filter?: FLUnit; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | filter | | ' ? {clock: Clock; source: Source; filter: FLUnit; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | ' ? {source: Source; clock?: never; filter?: FLUnit; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | ' ? {source: Source; clock?: never; filter: FLUnit; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | ' ? {clock: Clock; source?: never; filter?: FLUnit; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | ' ? {clock: Clock; source?: never; filter: FLUnit; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : [message: {error: 'filter unit should has boolean type'; got: UnitValue}] : FLBool extends BooleanConstructor ? Mode extends Mode_Flt_Fn ? [config: ( Mode extends 'clock | source | filter | fn | ' ? {clock: Clock; source: Source; filter?: FLBool; fn?: FNAltArg; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | ' ? {source: Source; clock?: never; filter?: FLBool; fn?: FNAltArg; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | ' ? {clock: Clock; source?: never; filter?: FLBool; fn?: FNAltArg; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : [config: ( Mode extends 'clock | source | filter | | ' ? {clock: Clock; source: Source; filter: FLBool; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | ' ? {source: Source; clock?: never; filter: FLBool; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | ' ? {clock: Clock; source?: never; filter: FLBool; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : FilterFun extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => src is FNInfSource : (src: TypeOfSource) => src is FNInfSource : Clock extends Units ? (clk: TypeOfClock) => clk is FNInfClock : never ) ? Mode extends Mode_Flt_Fn ? FNInf extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: FNInfSource, clk: TypeOfClock) => any : (src: FNInfSource) => any : Clock extends Units ? (clk: FNInfClock) => any : any ) ? [config: ( Mode extends 'clock | source | filter | fn | ' ? {clock: Clock; source: Source; filter?: FilterFun; fn?: FNInf; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | ' ? {source: Source; clock?: never; filter?: FilterFun; fn?: FNInf; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | ' ? {clock: Clock; source?: never; filter?: FilterFun; fn?: FNInf; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : [message: { error: 'fn should match inferred type' inferred: (Source extends Unit | SourceRecord ? FNInfSource : FNInfClock) fnArg: FNInf extends (arg: infer Arg) => any ? Arg : never }] : [config: ( Mode extends 'clock | source | filter | | ' ? {clock: Clock; source: Source; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | ' ? {source: Source; clock?: never; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | ' ? {clock: Clock; source?: never; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : FilterFun extends ( Source extends Unit | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => any : (src: TypeOfSource) => any : Clock extends Units ? (clk: TypeOfClock) => any : never ) ? ReturnType extends boolean ? [config: ( Mode extends 'clock | source | filter | fn | ' ? {clock: Clock; source: Source; filter?: FilterFun; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | filter | | ' ? {clock: Clock; source: Source; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | fn | ' ? {source: Source; clock?: never; filter?: FilterFun; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | filter | | ' ? {source: Source; clock?: never; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | fn | ' ? {clock: Clock; source?: never; filter?: FilterFun; fn?: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | filter | | ' ? {clock: Clock; source?: never; filter: FilterFun; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : [message: {error: 'filter function should return boolean'; got: ReturnType}] : [message: {error: 'filter should be function or unit'; got: FilterFun}] : Mode extends Mode_NoFlt ? [config: ( Mode extends 'clock | source | | fn | ' ? {clock: Clock; source: Source; filter?: never; fn: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | source | | | ' ? {clock: Clock; source: Source; filter?: never; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | | fn | ' ? {source: Source; clock?: never; filter?: never; fn: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends ' | source | | | ' ? {source: Source; clock?: never; filter?: never; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | | fn | ' ? {clock: Clock; source?: never; filter?: never; fn: FN; target?: never; greedy?: boolean; batch?: boolean; name?: string} : Mode extends 'clock | | | | ' ? {clock: Clock; source?: never; filter?: never; target?: never; greedy?: boolean; batch?: boolean; name?: string} : never ) & SomeFN] : never type DataSourceFunction = Source extends Unit | SourceRecord ? Clock extends Units ? (src: TypeOfSource, clk: TypeOfClock) => any : (src: TypeOfSource) => any : Clock extends Units ? (clk: TypeOfClock) => any : never type TypeOfTargetSoft>, Mode extends 'fnRet' | 'src' | 'clk'> = Target extends UnitTargetable ? Target extends UnitTargetable ? [SourceType] extends [Readonly] ? Target : WhichType extends ('void' | 'any') ? Target : IfAssignable : never : { [ K in keyof Target ]: Target[K] extends UnitTargetable ? [SourceType] extends [Readonly] ? Target[K] : WhichType extends ('void' | 'any') ? Target[K] : IfAssignable : never } type TypeOfTarget>, Mode extends 'fnRet' | 'src' | 'clk'> = Target extends UnitTargetable ? Target extends UnitTargetable ? [SourceType] extends [Readonly] ? Target : WhichType extends ('void' | 'any') ? Target : Mode extends 'fnRet' ? {fnResult: SourceType; targetType: TargetType} : Mode extends 'src' ? {sourceType: SourceType; targetType: TargetType} : {clockType: SourceType; targetType: TargetType} : never : { [ K in keyof Target ]: Target[K] extends UnitTargetable ? [SourceType] extends [Readonly] ? Target[K] : WhichType extends ('void' | 'any') ? Target[K] : Mode extends 'fnRet' ? {fnResult: SourceType; targetType: TargetType} : Mode extends 'src' ? {sourceType: SourceType; targetType: TargetType} : {clockType: SourceType; targetType: TargetType} : never } type ClockValueOf = T[keyof T] type TypeOfSource | SourceRecord> = Source extends Unit ? UnitValue : Source extends SourceRecord ? {[K in keyof Source]: UnitValue} : never type TypeOfClock> | never[]> = Clock extends never[] ? unknown : Clock extends Unit ? UnitValue : Clock extends Tuple> ? WhichType> extends 'any' ? never : K ]: Clock[K] }>>> extends 'never' ? any : UnitValue> extends 'any' ? never : K ]: Clock[K] }>> : Clock extends ReadonlyArray> ? UnitValue> : never type SourceRecord = Record> | RoTuple> type Units = Unit | Tuple> type UnitsTarget = UnitTargetable | Tuple> type InvalidUnitsTarget = Unit | Tuple> | ReadonlyArray> /* guard types */ type NonFalsy = T extends null | undefined | false | 0 | 0n | "" ? never : T; type GuardFilterSC = | ((source: GetSource, clock: GetClock) => boolean) | Store type GuardFilterS = | ((source: GetSource) => boolean) | Store type GuardFilterC = | ((clock: GetClock) => boolean) | Store type GuardResult = EventAsReturnType type GetGuardSource = F extends BooleanConstructor ? NonFalsy> : GetSource type GetGuardClock = F extends BooleanConstructor ? NonFalsy> : GetClock // --------------------------------------- /* user-defined typeguard: with target */ // SСT /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard, B = any, S extends Source = Source, C extends Clock = Clock, T extends Target = Target >(config: { source: S, clock: C, filter: (source: GetSource, clock: GetClock) => source is X, target: MultiTarget, name?: string, greedy?: boolean }): T // ST /** * Method for conditional event routing. * @deprecated use `sample({source, filter, target})` instead */ export function guard, S extends Source = Source, T extends Target = Target >(config: { source: S, filter: (source: GetSource) => source is X, target: MultiTarget, name?: string, greedy?: boolean }): T // СT /** * Method for conditional event routing. * @deprecated use `sample({clock, filter, target})` instead */ export function guard, C extends Clock = Clock, T extends Target = Target >(config: { clock: C, filter: (clock: GetClock) => clock is X, target: MultiTarget, name?: string, greedy?: boolean }): T /* user-defined typeguard: without target */ // SC /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard, B = any, S extends Source = Source, C extends Clock = Clock >(config: { source: S, clock: C, filter: (source: GetSource, clock: GetClock) => source is X, name?: string, greedy?: boolean }): GuardResult // S /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard, S extends Source = Source >(config: { source: S, filter: (source: GetSource) => source is X, name?: string, greedy?: boolean }): GuardResult // C /** * Method for conditional event routing. * @deprecated use `sample({clock, filter})` instead */ export function guard, C extends Clock = Clock >(config: { clock: C, filter: (clock: GetClock) => clock is X, name?: string, greedy?: boolean }): GuardResult // --------------------------------------- /* boolean fn or store: with target */ // SСT /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard = Source, C extends Clock = Clock, F extends GuardFilterSC = GuardFilterSC, T extends Target = Target >(config: { source: S, clock: C, filter: F, target: MultiTarget>, name?: string, greedy?: boolean }): T // ST /** * Method for conditional event routing. * @deprecated use `sample({source, filter, target})` instead */ export function guard = Source, F extends GuardFilterS = GuardFilterS, T extends Target = Target >(config: { source: S, filter: F, target: MultiTarget>, name?: string, greedy?: boolean }): T // СT /** * Method for conditional event routing. * @deprecated use `sample({clock, filter, target})` instead */ export function guard = Clock, F extends GuardFilterC = GuardFilterC, T extends Target = Target >(config: { clock: C, filter: F, target: MultiTarget>, name?: string, greedy?: boolean }): T /* boolean fn or store: without target */ // SC (units: BooleanConstructor) /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard(config: { source: Unit, clock: Unit, filter: BooleanConstructor, name?: string, greedy?: boolean }): GuardResult> // SC (units: boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard(config: { source: Unit, clock: Unit, filter: ((source: A, clock: B) => boolean) | Store, name?: string, greedy?: boolean }): GuardResult // SC /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard = Source, C extends Clock = Clock, F extends GuardFilterSC = GuardFilterSC, >(config: { source: S, clock: C, filter: F, name?: string, greedy?: boolean }): GuardResult> // S (unit: BooleanConstructor) /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard(config: { source: Unit, filter: BooleanConstructor, name?: string, greedy?: boolean }): GuardResult> // S (unit - boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard(config: { source: Unit, filter: ((source: A) => boolean) | Store, name?: string, greedy?: boolean }): GuardResult // S /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard = Source, F extends GuardFilterS = GuardFilterS, >(config: { source: S, filter: F, name?: string, greedy?: boolean }): GuardResult> // C (unit: boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({clock, filter})` instead */ export function guard(config: { clock: Unit, filter: BooleanConstructor, name?: string, greedy?: boolean }): GuardResult> // C (unit: boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({clock, filter})` instead */ export function guard(config: { clock: Unit, filter: ((clock: B) => boolean) | Store, name?: string, greedy?: boolean }): GuardResult // C /** * Method for conditional event routing. * @deprecated use `sample({clock, filter})` instead */ export function guard = Clock, F extends GuardFilterC = GuardFilterC, >(config: { clock: C, filter: F, name?: string, greedy?: boolean }): GuardResult> // --------------------------------------- // guard with source param // --------------------------------------- /* user-defined typeguard: with target */ // SСT /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard, B = any, S extends Source = Source, C extends Clock = Clock, T extends Target = Target >(source: S, config: { clock: C, filter: (source: GetSource, clock: GetClock) => source is X, target: MultiTarget, name?: string, greedy?: boolean }): T // ST /** * Method for conditional event routing. * @deprecated use `sample({source, filter, target})` instead */ export function guard, S extends Source = Source, T extends Target = Target >(source: S, config: { filter: (source: GetSource) => source is X, target: MultiTarget, name?: string, greedy?: boolean }): T /* user-defined typeguard: without target */ // SC /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard, B = any, S extends Source = Source, C extends Clock = Clock >(source: S, config: { clock: C, filter: (source: GetSource, clock: GetClock) => source is X, name?: string, greedy?: boolean }): GuardResult // S /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard, S extends Source = Source >(source: S, config: { filter: (source: GetSource) => source is X, name?: string, greedy?: boolean }): GuardResult // --------------------------------------- /* boolean fn or store: with target */ // SСT /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard = Source, C extends Clock = Clock, F extends GuardFilterSC = GuardFilterSC, T extends Target = Target >(source: S, config: { clock: C, filter: F, target: MultiTarget>, name?: string, greedy?: boolean }): T // ST /** * Method for conditional event routing. * @deprecated use `sample({source, filter, target})` instead */ export function guard = Source, F extends GuardFilterS = GuardFilterS, T extends Target = Target >(source: S, config: { filter: F, target: MultiTarget>, name?: string, greedy?: boolean }): T /* boolean fn or store: without target */ // SC (units: BooleanConstructor) /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard(source: Unit, config: { clock: Unit, filter: BooleanConstructor, name?: string, greedy?: boolean }): GuardResult> // SC (units: boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard(source: Unit, config: { clock: Unit, filter: ((source: A, clock: B) => boolean) | Store, name?: string, greedy?: boolean }): GuardResult // SC /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter})` instead */ export function guard = Source, C extends Clock = Clock, F extends GuardFilterSC = GuardFilterSC, >(source: S, config: { clock: C, filter: F, name?: string, greedy?: boolean }): GuardResult> // S (unit: BooleanConstructor) /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard(source: Unit, config: { filter: BooleanConstructor, name?: string, greedy?: boolean }): GuardResult> // S (unit: boolean fn or store) /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard(source: Unit, config: { filter: ((source: A) => boolean) | Store, name?: string, greedy?: boolean }): GuardResult // S /** * Method for conditional event routing. * @deprecated use `sample({source, filter})` instead */ export function guard = Source, F extends GuardFilterS = GuardFilterS, >(source: S, config: { filter: F, name?: string, greedy?: boolean }): GuardResult> // guard's last overload for `guard(source, config)` /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard< S extends Source, C extends Clock, F extends IfUnknown, Store | ((clock: GetClock) => boolean), IfUnknown, Store | ((source: GetSource) => boolean), Store | ((source: GetSource, clock: GetClock) => boolean) > >, T extends Target >(source: S, config: { clock?: C, filter: F, target: F extends (value: any, ...args: any) => value is infer X ? MultiTarget : MultiTarget>, name?: string, greedy?: boolean }): T // guard's last overload for `guard(config)` /** * Method for conditional event routing. * @deprecated use `sample({clock, source, filter, target})` instead */ export function guard< S extends Source, C extends Clock, F extends IfUnknown, Store | ((clock: GetClock) => boolean), IfUnknown, Store | ((source: GetSource) => boolean), Store | ((source: GetSource, clock: GetClock) => boolean) > >, T extends Target >(config: { source?: S, clock?: C, filter: F, target: F extends (value: any, ...args: any) => value is infer X ? MultiTarget : MultiTarget, GetGuardClock, GetGuardSource > >, name?: string, greedy?: boolean }): T /* attach types */ type StoreShape = Store | Combinable type GetShapeValue = T extends Store ? S : GetCombinedValue /** * Method for creating state-dependent effect and transforming effect payloads * @returns new effect */ export function attach< Params, States extends StoreShape, FX extends Effect >(config: { source: States effect: FX mapParams: (params: Params, states: GetShapeValue) => NoInfer> name?: string }): Effect, EffectError> /** * Method for transforming effect payloads * @returns new effect */ export function attach any), FX extends Effect>(config: { effect: FX mapParams: FN extends (...args: any[]) => NoInfer> ? FN : never name?: string }): FN extends (...args: infer Args) => NoInfer> ? Effect< Args['length'] extends 0 ? void : 0 | 1 extends Args['length'] ? Args[0] | void : Args[0], EffectResult, EffectError > : never /** * Method for transforming effect payloads * @returns new effect */ export function attach>(config: { effect: FX mapParams: (params: Params) => NoInfer> name?: string }): Effect, EffectError> /** * Method for passing state values to effects * @returns new effect */ export function attach< States extends StoreShape, FX extends Effect, any, any> >(config: { source: States effect: FX name?: string }): Effect, EffectError> /** * Creates state-dependent effect with provided function handler. * Allows the one to omit intermediate effects and declare effect handler right next to data source * @returns new effect */ export function attach< States extends StoreShape, FX extends (state: GetShapeValue, params: any) => any >(config: { source: States effect: FX domain?: Domain name?: string }): FX extends (source: any, ...args: infer Args) => infer Done ? Effect, Awaited> : never /** * Creates independent instance of given effect. Used to add subscribers to effect call in a particular business case * @returns new effect linked to given one */ export function attach< FX extends Effect, >(config: { effect: FX name?: string }): Effect, EffectResult, EffectError> /** * Method for creating state-dependent effect and transforming effect payload * @returns new effect */ export function attach< States extends StoreShape, FX extends Effect, FN extends ((params: any, source: GetShapeValue) => NoInfer>) >(config: { source: States effect: FX mapParams: FN name?: string }): Effect[0] , EffectResult, EffectError> type CombineState = State[keyof State] extends Store // ensure that CombineState will be used only with explicit generics // without Store type in them ? never : { [K in keyof State]: | State[K] | (undefined extends State[K] ? Store> : Store) } /** * Bind units and links between them created inside `cb` callback to unit or graph node to erase during `clearNode` call * Low level tool, usually absent in common applications * @param unit parent unit or graph node * @param cb callback assumed to create some units */ export function withRegion(unit: Unit | Node, cb: () => T): T /** * Helper type for combine */ type CombVal = T extends Store ? StoreValue : T /** * Convert given stores to store with array which values updated upon changes in given ones * @returns derived store */ export function combine>( store: T, ): T extends Store ? Store<[R]> : never /** * Convert array of stores to store with array which values updated upon changes in given ones * @param tuple array of stores * @returns derived store updated upon changes in given ones */ export function combine( tuple: State, ): Store<{[K in keyof State]: State[K] extends Store ? U : State[K]}> /** * Convert object with stores to object store which fields updated upon changes in given ones * @param shape object with stores * @returns derived store updated upon changes in given ones */ export function combine(shape: CombineState): Store /** * Convert object with stores to object store which fields updated upon changes in given ones * @param shape object with stores * @returns derived store updated upon changes in given ones */ export function combine( shape: State, ): Store<{[K in keyof State]: State[K] extends Store ? U : State[K]}> /** * Creates derived store from given one, transforming value using the function * @param source source store * @param fn transformer function, accepts a store value * @returns derived store updated upon changes in given one */ export function combine(source: Store, fn: (source: A) => R, config?: {skipVoid: boolean}): Store /** * Convert array of stores into derived store, transforming values using the function * @param tuple array of stores * @param fn transformer function, accepts an array of values * @returns derived store updated upon changes in given ones */ export function combine( tuple: State, fn: ( tuple: {[K in keyof State]: State[K] extends Store ? U : State[K]}, ) => R, config?: {skipVoid: boolean} ): Store /** * Convert object with stores into derived store, transforming values using the function * @param shape object with stores * @param fn transformer function, accepts object with values * @returns derived store updated upon changes in given ones */ export function combine( shape: State, fn: ( shape: {[K in keyof State]: State[K] extends Store ? U : State[K]}, ) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, fn: (a: CombVal, b: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, fn: (a: CombVal, b: CombVal, c: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, g: G, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal, g: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * * > Consider using `combine(arrayOfStores, arrayOfValues => ...)` instead * * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal, g: CombVal, h: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * * > Consider using `combine(arrayOfStores, arrayOfValues => ...)` instead * * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal, g: CombVal, h: CombVal, i: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * * > Consider using `combine(arrayOfStores, arrayOfValues => ...)` instead * * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal, g: CombVal, h: CombVal, i: CombVal, j: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores into derived store, transforming values using the function * * > Consider using `combine(arrayOfStores, arrayOfValues => ...)` instead * * @param fn transformer function, accepts store values in separate arguments * @returns derived store updated upon changes in given ones */ export function combine( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, fn: (a: CombVal, b: CombVal, c: CombVal, d: CombVal, e: CombVal, f: CombVal, g: CombVal, h: CombVal, i: CombVal, j: CombVal, k: CombVal) => R, config?: {skipVoid: boolean} ): Store /** * Convert given stores to store with array which values updated upon changes in given ones * @returns derived store */ export function combine | any>>( ...stores: T ): Store<{[K in keyof T]: T[K] extends Store ? U : T[K]}> /** * Fully isolated instance of application. The primary purpose of scope includes SSR and testing */ export interface Scope extends Unit { getState(store: Store): T } export type ValueMap = Map, any> | Array<[StoreWritable, any]> | {[sid: string]: any} /** * Fill stores with given values in provided scope or domain * * @deprecated use `fork({values})` instead */ export function hydrate(domainOrScope: Domain | Scope, config: {values: ValueMap}): void /** * Serialize store values from given scope * @returns object with saved values */ export function serialize( scope: Scope, options?: {ignore?: Array>; onlyChanges?: boolean}, ): {[sid: string]: any} /** * Bind event to a scope to be called later. * * When `scope` is not provided this method retrieve scope implicitly from scope of the handler (effect handler or watch function) inside which it's being called * @param unit event to bind * @returns function which will trigger an event in a given scope */ export function scopeBind(unit: EventCallable, opts?: {scope?: Scope; safe?: boolean}): (payload: T) => void /** * Bind effect to a scope to be called later. * * When `scope` is not provided this method retrieve scope implicitly from scope of the handler (effect handler or watch function) inside which it's being called * @param unit effect to bind * @returns function which will trigger an effect in a given scope and returns a promise with a result */ export function scopeBind(unit: Effect, opts?: {scope?: Scope; safe?: boolean}): (params: P) => Promise /** * Bind arbitary callback to a scope to be called later. * When `scope` is not provided this method retrieve scope implicitly from scope of the handler (effect handler or watch function) inside which it's being called * @param unit effect to bind * @returns function which will trigger an effect in a given scope and returns a promise with a result */ export function scopeBind(fn: T, opts?: {scope?: Scope; safe?: boolean}): T // fork types type Handlers = Map, Function> | Array<[Effect, Function]> | {[sid: string]: Function}; type SerializedState = Record; type LegacyMap = Map, any> type StorePair = [StoreWritable, T]; /** * Creates isolated instance of application. Primary purposes of this method are SSR and testing. * @param config optional configuration object with initial store values and effect handlers * @returns new scope */ export function fork( config?: { values?: StorePair[] | SerializedState | LegacyMap, handlers?: Handlers }, ): Scope // legacy overloads /** * Creates isolated instance of application. Primary purposes of this method are SSR and testing. * * @deprecated use `fork({values, handlers})` instead * * @param domain optional root domain * @param config optional configuration object with initial store values and effect handlers * @returns new scope */ export function fork( domain: Domain, config?: { values?: SerializedState | LegacyMap | Array<[StoreWritable, any]>, handlers?: Handlers; }, ): Scope /** * Run effect in scope and wait for all triggered effects to settle. This method never throw an error * @param unit effect to run * @returns promise with status object for given effect, will resolve when there will be no pending effects in given scope */ export function allSettled>( unit: FX, config: {scope: Scope; params: EffectParams}, ): Promise<{status: 'done', value: EffectResult} | {status: 'fail'; value: EffectError}> /** * Run effect withot arguments in scope and wait for all triggered effects to settle. This method never throw an error * @param unit effect to run * @returns promise with status object for given effect, will resolve when there will be no pending effects in given scope */ export function allSettled>( unit: FX, config: {scope: Scope}, ): Promise<{status: 'done', value: EffectResult} | {status: 'fail'; value: EffectError}> /** * Run unit in scope and wait for all triggered effects to settle. This method never throw an error * @param unit event or store to run * @returns void promise, will resolve when there will be no pending effects in given scope */ export function allSettled( unit: UnitTargetable, config: {scope: Scope; params: T}, ): Promise /** * Run unit without arguments in scope and wait for all triggered effects to settle. This method never throw an error * @param unit event or store to run * @returns void promise, will resolve when there will be no pending effects in given scope */ export function allSettled( unit: UnitTargetable, config: {scope: Scope}, ): Promise /** * Check for any ongoing computations in provided scope and wait for them to settle. * @param scope {Scope} * @returns void promise, will resolve when there will be no pending effects in given scope */ export function allSettled(scope: Scope): Promise export function createWatch({ unit, fn, scope, batch, }: { unit: Unit | Unit[] fn: (value: T) => any scope?: Scope batch?: boolean }): Subscription