/** * Common effects apis. Only used to reduce repetition. * There is no js module backing this up. */ import { Action } from 'redux'; import { Task, TakeableChannel, FlushableChannel, Buffer, PuttableChannel } from 'redux-saga'; import * as E from 'redux-saga/effects'; // Gives you the type of a field K in type T type FieldType = T[K]; interface TakeEffectApi { (pattern?: E.Pattern): R; (channel: TakeableChannel): R; } interface PutEffectApi { (action: A): R; (channel: PuttableChannel, action: T): R; } /** * Contains effect functions with variable return type. * Method arguments should be same as in Redux-Saga. * Return type is generic as signatures are used at different places * with method chaining. */ interface EffectApi { actionChannel(pattern: E.Pattern, buffer?: Buffer): R; apply(context: T, fnName: K, ...args: any[]): R; apply(context: any, fn: Function, ...args: any[]): R; cps(fn: Function, ...args: any[]): R; getContext(key: string): R; setContext(prop: { [key: string]: any }): R; put: PutEffectApi; putResolve: PutEffectApi; race(effects: { [key: string]: E.Effect }): R; race(effects: E.Effect[]): R; select(selector?: (state: S, ...args: any[]) => any, ...args: any[]): R; call(fn: [T, Function], ...args: any[]): R; call(fn: [T, K], ...args: any[]): R; call(fn: Function, ...args: any[]): R; fork(fn: Function, ...args: any[]): R; spawn(fn: Function, ...args: any[]): R; take: TakeEffectApi; takeMaybe: TakeEffectApi; all(effects: { [key: string]: E.Effect }): R; all(effects: E.Effect[]): R; cancel(task: Task): R; cancelled(): R; flush(channel: FlushableChannel): R; join(...tasks: Task[]): R; delay(ms: number, val?: any): R; } /** * Extends a method from EffectApi with * - like(param: Partial) * - methods named same as a EffectDescriptor property (example: fn in CallEffectDescriptor) * @template KEff Key (fieldName) in EffectApi * @template Desc EffectDescriptor * @template KDesc Key in EffectDescriptor that will be its own method (example :fn) * @template R Result of the method call (for method chaining in different implementations) */ type ExtendedEffectApi, Desc, KDesc extends keyof Desc, R> = FieldType, KEff> & { [Key in KDesc]: (param: Desc[KDesc]) => R; } & { like(effect: Partial): R; }; // Can't use 'ExtendedEffectApi here because 'actionType' is used // instead of 'action' (differs from saga implementation). type PutEffectEx = FieldType, 'put'> & FieldType, 'putResolve'> & { like(effect: Partial>): R; actionType(action: string): R; actionType(action: A): R; resolve: PutEffectEx }; /** * Certain effects are extended with: * - 'like' method that takes partial descriptor * - Shortcut for EffectDescriptor properties (like fn in CallEffectDescriptor) */ interface EffectApiEx { actionChannel: ExtendedEffectApi<'actionChannel', E.ActionChannelEffectDescriptor, 'pattern', R>; apply: ExtendedEffectApi<'apply', E.CallEffectDescriptor, 'fn', R>; cps: ExtendedEffectApi<'cps', E.CallEffectDescriptor, 'fn', R>; select: ExtendedEffectApi<'select', E.SelectEffectDescriptor, 'selector', R>; call: ExtendedEffectApi<'call', E.CallEffectDescriptor, 'fn', R>; fork: ExtendedEffectApi<'fork', E.CallEffectDescriptor, 'fn', R>; spawn: ExtendedEffectApi<'spawn', E.CallEffectDescriptor, 'fn', R>; put: PutEffectEx; putResolve: PutEffectEx; }