/** * A typical api function: takes an arbitrary number of arguments of type A * and returns a Promise which resolves with a specific response type of R. */ export type ApiFn = (...args: A) => Promise; /** * An updater function: has a similar signature with the original api function, * but doesn't return anything because it only triggers new api calls. */ export type UpdaterFn = (...args: A) => void; /** * A simple data reader function: returns the response type R. */ type DataFn = () => R; /** * A lazy data reader function: can return the response type R or `undefined`. */ type LazyDataFn = () => R | undefined; /** * A modifier function which takes as only argument the response type R and returns a different type M. */ export type ModifierFn = (response: R) => M; /** * A data reader with a modifier function, * returning the modified type M instead of the response type R. */ type ModifiedDataFn = (modifier: ModifierFn) => M; /** * A lazy data reader with a modifier function, * returning the modified type M instead of the response type R, or `undefined`. */ type LazyModifiedDataFn = (modifier: ModifierFn) => M | undefined; // Finally, our actual eager and lazy implementations will use both versions (with and without a modifier function), // so we need overloaded types that will satisfy them simultaneously /** * A data reader function with an optional modifier function. */ export type DataOrModifiedFn = DataFn & ModifiedDataFn; /** * A lazy data reader function with an optional modifier function. */ export type LazyDataOrModifiedFn = LazyDataFn & LazyModifiedDataFn;