Probably something in these lines:
type ChainPFn <A, B> = (a: A) => Promise<B>;
const chainP = <A, B, E = UnknownError>(fn: ChainPFn<A, B>, handler?: (err: unknown) => E) =>
chain(
// TODO: need to wrap fn inside a try catch
(a: A) => Task.fromPromise(fn(a))
.catch(err => {
if (handler) {
return Task.reject(handler(err));
} else {
return Task.reject(new UnknownError(err) as any as E);
}
})
)
;
This can allow something like
async function foo (n: number) {
if (n === 1) {
throw 'Buu';
}
return n;
}
// If the function fails then the error is wrapped in UnknownError
Task.resolve(1).pipe(
chainP(val => foo(val))
); // Task<number, UnknownError>
// If you provide a handler you can control the type of error
Task.resolve(1).pipe(
chainP(val => foo(val), err => err as string)
); // Task<number, UnknownError | string>