Skip to content

Instantly share code, notes, and snippets.

@matttti
Created January 28, 2017 09:30
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save matttti/ae0d65bf534cb84a0dbe4ddd3b0f759c to your computer and use it in GitHub Desktop.
Save matttti/ae0d65bf534cb84a0dbe4ddd3b0f759c to your computer and use it in GitHub Desktop.
[redux-saga]: flow-typing of yield return values
import * as IOEffects from 'redux-saga/effects'
export function * select (...args) {
return yield IOEffects.select(...args)
}
export function * put (...args) {
return yield IOEffects.put(...args)
}
export function * call (...args) {
return yield IOEffects.call(...args)
}
export function * cps (...args) {
return yield IOEffects.cps(...args)
}
export function * fork (...args) {
return yield IOEffects.fork(...args)
}
export function * cancelled () {
return yield IOEffects.cancelled()
}
// @flow
import type { Channel, Task } from 'redux-saga'
declare type Context = Object;
declare type FnSpread<T, R> = (...args: Array<T>) => R | Promise<R>;
declare type Fn0<R> = () => R | Promise<R> | Generator<*,R,*>;
declare type Fn1<T1, R> = (t1: T1) => R | Promise<R> | Generator<*,R,*>;
declare type Fn2<T1, T2, R> = (t1: T1, t2: T2) => R | Promise<R> | Generator<*,R,*>;
declare type Fn3<T1, T2, T3, R> = (t1: T1, t2: T2, t3: T3) => R | Promise<R> | Generator<*,R,*>;
declare type Fn4<T1, T2, T3, T4, R> = (t1: T1, t2: T2, t3: T3, t4: T4) => R | Promise<R> | Generator<*,R,*>;
declare type Fn5<T1, T2, T3, T4, T5, R> = (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => R | Promise<R> | Generator<*,R,*>;
declare type Fn6<T1, T2, T3, T4, T5, T6, R> = (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => R | Promise<R> | Generator<*,R,*>;
/* ------------------ SELECT Stuff ------------------ */
declare type SelectFnSpread<T, R> = (state: any, ...args: Array<T>) => R;
declare type SelectFn0<R> = ((state: any) => any) & (() => R);
declare type SelectFn1<T1, R> = (state: any, t1: T1) => R;
declare type SelectFn2<T1, T2, R> = (state: any, t1: T1, t2: T2) => R;
declare type SelectFn3<T1, T2, T3, R> = (state: any, t1: T1, t2: T2, t3: T3) => R;
declare type SelectFn4<T1, T2, T3, T4, R> = (state: any, t1: T1, t2: T2, t3: T3, t4: T4) => R;
declare type SelectFn5<T1, T2, T3, T4, T5, R> = (state: any, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => R;
declare type SelectFn6<T1, T2, T3, T4, T5, T6, R> = (state: any, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => R;
declare type SelectFn =
& (<R, Fn: SelectFn<R>>(selector: Fn, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, R, Fn: SelectFn1<T1, R>>(selector: Fn, t1: T1, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, R, Fn: SelectFn2<T1, T2, R>>(selector: Fn, t1: T1, t2: T2, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, R, Fn: SelectFn3<T1, T2, T3, R>>(selector: Fn, t1: T1, t2: T2, t3: T3, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, R, Fn: SelectFn4<T1, T2, T3, T4, R>>(selector: Fn, t1: T1, t2: T2, t3: T3, t4: T4, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, R, Fn: SelectFn5<T1, T2, T3, T4, T5, R>>(selector: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, T6, R, Fn: SelectFn6<T1, T2, T3, T4, T5, T6, R>>(selector: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, ...rest: Array<void>) => Generator<*, R, *>)
& (<T, R, Fn: SelectFnSpread<T, R>>(selector: Fn, t1: T, t2: T, t3: T, t4: T, t5: T, t6: T, ...rest: Array<T>) => Generator<*, R, *>)
/* ------------------ CALL Stuff ------------------ */
declare type ContextCallFn =
& (<R, C: Context, Fn: Fn0<R>>(cfn: [C, Fn], ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, R, C: Context, Fn: Fn1<T1, R>>(cfn: [C, Fn], t1: T1, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, R, C: Context, Fn: Fn2<T1, T2, R>>(cfn: [C, Fn], t1: T1, t2: T2, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, R, C: Context, Fn: Fn3<T1, T2, T3, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, R, C: Context, Fn: Fn4<T1, T2, T3, T4, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, R, C: Context, Fn: Fn5<T1, T2, T3, T4, T5, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, T6, R, C: Context, Fn: Fn6<T1, T2, T3, T4, T5, T6, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, ...rest: Array<void>) => Generator<*, R, *>)
& (<T, R, C: Context, Fn: FnSpread<T, R>>(cfn: [C, Fn], t1: T, t2: T, t3: T, t4: T, t5: T, t6: T, ...args: Array<T>) => Generator<*, R, *>);
declare type CallFn =
& ContextCallFn
& (<R, Fn: Fn0<R>>(fn: Fn) => Generator<*, R, *>)
& (<T1, R, Fn: Fn1<T1, R>>(fn: Fn, t1: T1) => Generator<*, R, *>)
& (<T1, T2, R, Fn: Fn2<T1, T2, R>>(fn: Fn, t1: T1, t2: T2) => Generator<*, R, *>)
& (<T1, T2, T3, R, Fn: Fn3<T1, T2, T3, R>>(fn: Fn, t1: T1, t2: T2, t3: T3) => Generator<*, R, *>)
& (<T1, T2, T3, T4, R, Fn: Fn4<T1, T2, T3, T4, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, R, Fn: Fn5<T1, T2, T3, T4, T5, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, T6, R, Fn: Fn6<T1, T2, T3, T4, T5, T6, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => Generator<*, R, *>)
& (<T, R, Fn: FnSpread<T, R>>(fn: Fn, ...args: Array<T>) => Generator<*, R, *>);
/* ------------------ CPS Stuff ------------------ */
declare type CallbackFn<R> = (error: any, ret: R) => void;
declare type CpsFnSpread<T, R> = (cb: CallbackFn<R>, ...args: Array<T>) => any;
declare type CpsFn0<R> = (cb: CallbackFn<R>) => any;
declare type CpsFn1<T1, R> = (t1: T1, CallbackFn<R>) => any;
declare type CpsFn2<T1, T2, R> = (t1: T1, t2: T2, cb: CallbackFn<R>) => any;
declare type CpsFn3<T1, T2, T3, R> = (t1: T1, t2: T2, t3: T3, cb: CallbackFn<R>) => any;
declare type CpsFn4<T1, T2, T3, T4, R> = (t1: T1, t2: T2, t3: T3, t4: T4, cb: CallbackFn<R>) => any;
declare type CpsFn5<T1, T2, T3, T4, T5, R> = (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, cb: CallbackFn<R>) => any;
declare type CpsFn6<T1, T2, T3, T4, T5, T6, R> = (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, cb: CallbackFn<R>) => any;
declare type ContextCpsFn =
& (<R, C: Context, Fn: CpsFn0<R>>(cfn: [C, Fn], ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, R, C: Context, Fn: CpsFn1<T1, R>>(cfn: [C, Fn], t1: T1, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, R, C: Context, Fn: CpsFn2<T1, T2, R>>(cfn: [C, Fn], t1: T1, t2: T2, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, R, C: Context, Fn: CpsFn3<T1, T2, T3, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, R, C: Context, Fn: CpsFn4<T1, T2, T3, T4, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, R, C: Context, Fn: CpsFn5<T1, T2, T3, T4, T5, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, T6, R, C: Context, Fn: CpsFn6<T1, T2, T3, T4, T5, T6, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, ...rest: Array<void>) => Generator<*, R, *>)
& (<T, R, C: Context, Fn: CpsFnSpread<T, R>>(cfn: [C, Fn], t1: T, t2: T, t3: T, t4: T, t5: T, t6: T, ...args: Array<T>) => Generator<*, R, *>);
declare type CpsFn =
& ContextCpsFn
& (<R, Fn: CpsFn0<R>>(fn: Fn, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, R, Fn: CpsFn1<T1, R>>(fn: Fn, t1: T1, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, R, Fn: CpsFn2<T1, T2, R>>(fn: Fn, t1: T1, t2: T2, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, R, Fn: CpsFn3<T1, T2, T3, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, R, Fn: CpsFn4<T1, T2, T3, T4, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, R, Fn: CpsFn5<T1, T2, T3, T4, T5, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, ...rest: Array<void>) => Generator<*, R, *>)
& (<T1, T2, T3, T4, T5, T6, R, Fn: CpsFn6<T1, T2, T3, T4, T5, T6, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, ...rest: Array<void>) => Generator<*, R, *>)
& (<T, R, Fn: CpsFnSpread<T, R>>(fn: Fn, ...args: Array<T>) => Generator<*, R, *>);
/* ------------------ FORK Stuff ------------------ */
declare type ContextForkFn =
& (<R, C: Context, Fn: Fn0<R>>(cfn: [C, Fn], ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, R, C: Context, Fn: Fn1<T1, R>>(cfn: [C, Fn], t1: T1, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, T2, R, C: Context, Fn: Fn2<T1, T2, R>>(cfn: [C, Fn], t1: T1, t2: T2, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, T2, T3, R, C: Context, Fn: Fn3<T1, T2, T3, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, R, C: Context, Fn: Fn4<T1, T2, T3, T4, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, T5, R, C: Context, Fn: Fn5<T1, T2, T3, T4, T5, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, T5, T6, R, C: Context, Fn: Fn6<T1, T2, T3, T4, T5, T6, R>>(cfn: [C, Fn], t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, ...rest: Array<void>) => Generator<*, Task, *>)
& (<T, R, C: Context, Fn: FnSpread<T, R>>(cfn: [C, Fn], t1: T, t2: T, t3: T, t4: T, t5: T, t6: T, ...args: Array<T>) => Generator<*, Task, *>);
declare type ForkFn =
& ContextForkFn
& (<R, Fn: Fn0<R>>(fn: Fn) => Generator<*, Task, *>)
& (<T1, R, Fn: Fn1<T1, R>>(fn: Fn, t1: T1) => Generator<*, Task, *>)
& (<T1, T2, R, Fn: Fn2<T1, T2, R>>(fn: Fn, t1: T1, t2: T2) => Generator<*, Task, *>)
& (<T1, T2, T3, R, Fn: Fn3<T1, T2, T3, R>>(fn: Fn, t1: T1, t2: T2, t3: T3) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, R, Fn: Fn4<T1, T2, T3, T4, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, T5, R, Fn: Fn5<T1, T2, T3, T4, T5, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => Generator<*, Task, *>)
& (<T1, T2, T3, T4, T5, T6, R, Fn: Fn6<T1, T2, T3, T4, T5, T6, R>>(fn: Fn, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => Generator<*, Task, *>)
& (<T, R, Fn: FnSpread<T, R>>(fn: Fn, ...args: Array<T>) => Generator<*, R, *>);
/* ------------------ Effects without return types ------------------ */
declare type PutFn = {
<T: Object>(action: T): any;
<T: Object>(channel: Channel, action: T): any;
}
declare type CancelledFn = () => Generator<*, bool, *>;
declare export var select : SelectFn;
declare export var call : CallFn;
declare export var put : PutFn;
declare export var cps : CpsFn;
declare export var fork : ForkFn;
declare export var cancelled : CancelledFn;
/* @flow */
import { call, select, cps, put, fork, cancelled } from './effect-generators'
import type { Task } from 'redux-saga'
function FCall (t1: string) : number {
return 123
}
function FSelect (state: any, t1: string) : number {
return 123
}
function FCps (t1: string, callback: (error: any, res: number) => void) : void {
return callback(null, 123)
}
function * testSaga () : Generator<*, *, *> {
const ctx = {}
const a1 : number = yield * call(FCall, 'abc')
const a2 : number = yield * call([ctx, FCall], 'abc')
// $FlowFixMe
const a3 : string = yield * call(FCall, 'abc')
// $FlowFixMe
const a4 : number = yield * call(FCall, 123)
// $FlowFixMe
const a5 : number = yield * call([123, FCall], 'abc')
const b1 : number = yield * select(FSelect, 'abc')
// $FlowFixMe
const b2 : string = yield * select(FSelect, 'abc')
// $FlowFixMe
const b3 : number = yield * select(FSelect, 123)
const c1 : number = yield * cps(FCps, 'abc')
const c2 : number = yield * cps([ctx, FCps], 'abc')
// $FlowFixMe
const c3 : string = yield * cps(FCps, 'abc')
// $FlowFixMe
const c4 : number = yield * cps(FCps, 123)
// $FlowFixMe
const c5 : number = yield * cps([123, FCps], 'abc')
yield * put({}, 'abc')
const cancelled1: bool = yield * cancelled()
// $FlowFixMe
const cancelled2: number = yield * cancelled() // anti 'any' check
const t1 : Task = yield * fork(FCall, 'abc')
const t2 : Task = yield * fork([ctx, FCall], 'abc')
// $FlowFixMe
const t3 : Task = yield * fork(FCall, 123)
// $FlowFixMe
const t4 : Task = yield * fork([123, FCall], 'abc')
}
@matttti
Copy link
Author

matttti commented Jan 28, 2017

required dependencies:
redux-saga
redux-saga flow-typed declarations

  • lines below $FlowFixMe are supposed to fail
  • not all effects are implemented (yet)

@samueljseay
Copy link

samueljseay commented Sep 15, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment