Skip to content

Instantly share code, notes, and snippets.

@savagematt
Created August 7, 2019 14:02
Show Gist options
  • Save savagematt/109b9274f5987c1c168b766beecbe860 to your computer and use it in GitHub Desktop.
Save savagematt/109b9274f5987c1c168b766beecbe860 to your computer and use it in GitHub Desktop.
scenario withX
export type ReturnValue<T> = T extends (...args: any[]) => infer RETURN
? RETURN
: T;
export type Args<T> = T extends (...args: infer ARGS) => any
? ARGS
: [];
export type CallAsStep<C, T> = (...args: Args<T>) => Step<C, Promise<Resolve<ReturnValue<T>>>>;
export type StepGenerator<C, T> = { [K in keyof T]: CallAsStep<C, T[K]> };
export type Resolve<T> = T extends Promise<infer U> ? U :T;
export function withX<C, T>(f: (c: C) => T, tPrototype: object): StepGenerator<C, Resolve<T>> {
function asStep<K extends keyof T>(k: K): CallAsStep<C, T[K]> {
return (...args: Args<T[K]>): Step<C, Promise<Resolve<ReturnValue<T[K]>>>> => {
return async (c: C): Promise<Resolve<ReturnValue<T[K]>>> => {
const target = await f(c);
const value = target[k];
return typeof value === 'function'
? await (value as any).call(target, ...args) as Resolve<ReturnValue<T[K]>>
: await value as Resolve<ReturnValue<T[K]>>;
}
};
}
return Object.getOwnPropertyNames(tPrototype).reduce(
(ret: StepGenerator<C, T>, k: any) => {
ret[k as keyof T] = asStep(k);
return ret;
},
{}) as any;
}
@savagematt
Copy link
Author

export function withToaster(id?: string): StepGenerator<ScenarioContext, Toaster> {
  return withX((c) => c.toaster(id), Toaster.prototype);
}
scenario(context,
  withToaster("mytoaster").addToast()
)

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