UNPKG

@zedux/core

Version:

A high-level, declarative, composable form of Redux

249 lines (207 loc) 5.89 kB
import { Store } from './api/createStore' // Same workaround rxjs uses for Symbol.observable: declare global { interface SymbolConstructor { readonly observable: symbol } } export declare const observable: string | symbol export interface Action< Payload = any, Type extends string = string, Meta = any > { meta?: Meta payload?: Payload type: Type } export type ActionChain<Payload = any, Type extends string = string> = | ActionMeta<Payload, Type> | Action<Payload, Type> export type ActionCreator< Payload = any, Type extends string = string > = Payload extends undefined ? () => Action<Payload, Type> : (payload: Payload) => Action<Payload, Type> export type ActionFactory< Payload = any, Type extends string = string > = ActionCreator<Payload, Type> & { type: Type } export type ActionFactoryPayloadType<A extends ActionFactory> = A extends ActionFactory<infer T> ? T : never export type ActionFactoryActionType<A extends ActionFactory> = A extends ActionFactory<infer P, infer T> ? { payload: P; type: T } : never export type ActionFactoryTypeType<A extends ActionFactory> = A extends ActionFactory<any, infer T> ? T : never export interface ActionMeta< Payload = any, Type extends string = string, Data = any > { metaType: string metaData?: Data meta?: undefined // to make this type compatible with Action type payload: ActionChain<Payload, Type> type?: undefined // to make this type compatible with Action type } export type ActionMetaType<A extends Action> = A extends Action< any, any, infer T > ? T : never export type ActionPayloadType<A extends Action> = A extends Action<infer T> ? T : never export type ActionType = string export type ActionTypeType<A extends Action> = A extends Action<any, infer T> ? T : never export type Branch<T = any> = { [K in keyof T]: HierarchyDescriptor<T[K]> } export type Composable<T = any> = (arg: T) => T export type Dispatchable = ActionChain export type Dispatcher<State = any> = (dispatchable: Dispatchable) => State export interface StoreEffect< State = any, S extends Store<State> = Store<State> > { action: ActionChain error?: unknown newState: State oldState?: State store: S } export type EffectType = string export type EffectsSubscriber< State = any, S extends Store<State> = Store<State> > = (storeEffect: StoreEffect<State, S>) => any export type ErrorSubscriber = (error: unknown) => any export interface HierarchyConfig<T = any> { clone: (node: T) => T create: () => T get: (node: T, key: string) => any isNode: (node: any) => boolean iterate: (node: T, callback: (key: string, val: any) => void) => void set: (node: T, key: string, val: any) => T size: (node: T) => number } /** * Describes a store's dependency tree. A store can have any number of reducers * or child stores nested indefinitely. * * ```ts * import { createStore } from '@zedux/core' * * const store = createStore({ * a: { * b: childStoreB, * c: childStoreC, * d: { * e: reducerE, * } * } * }) * ``` */ export type HierarchyDescriptor<State = any> = | Branch<State> | Store<State> | Reducer<State> | null /** * After a store is created, TS knows the hierarchy shape and we can be more * intelligent in e.g. the store's `.use()` method */ export type KnownHierarchyDescriptor<State = any> = State extends Record< any, any > ? State extends any[] ? // arrays match the Record type but can't be `Branch`es Store<State> | Reducer<State> | null : Branch<State> | Store<State> | Reducer<State> | null : Store<State> | Reducer<State> | null export interface Job { flags?: number id?: string task: () => void /** * 0 - UpdateStore * 1 - InformSubscribers * 2 - EvaluateGraphNode * 3 - UpdateExternalDependent * 4 - RunEffect */ type: 0 | 1 | 2 | 3 | 4 } export type NextSubscriber<State = any> = ( newState: State, prevState: State | undefined, action: ActionChain ) => any export interface Observable<T = any> { subscribe(subscriber: (value: T) => any): Subscription } export type Reactable<Payload = any, Type extends string = any> = | ActionFactory<Payload, Type> | Type export type RecursivePartial<T> = T extends Record<string, any> ? { [P in keyof T]?: RecursivePartial<T[P]> } : T export type Reducer<State = any> = ( state: State | undefined, action: Action ) => State export interface Scheduler { scheduleNow(newJob: Job): void } export type Selector<State = any, Derivation = any> = ( state: State ) => Derivation export type SetState<State = any, PartialState extends Partial<State> = any> = ( state: State ) => PartialState export type Settable<State = any, StateIn = State> = | ((state: StateIn) => State) | State export type StateSetter<State = any> = (settable: Settable<State>) => State export type StoreStateType<S extends Store> = S extends Store<infer T> ? T : never export type SubReducer< State = any, Payload = any, Type extends string = any, Meta = any > = ( state: State, payload: Payload, action: Action<Payload, Type, Meta> ) => State export type Subscriber<State = any, S extends Store<any> = Store<any>> = | NextSubscriber<State> | SubscriberObject<State, S> export interface SubscriberObject< State = any, S extends Store<State> = Store<State> > { next?: NextSubscriber<State> effects?: EffectsSubscriber<State, S> error?: ErrorSubscriber } export interface Subscription { unsubscribe(): void } export interface ReducerBuilder<State = any> extends Reducer<State> { reduce<Type extends string = string, Payload = any>( reactable: Reactable<Payload, Type> | Reactable<Payload, Type>[], // TODO: allow multiple actions with different payload types reducer: SubReducer<State, Payload> ): ReducerBuilder<State> }