diff --git a/src/Task/Task.ts b/src/Task/Task.ts index 4a1fa3df..8e01c206 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -753,6 +753,18 @@ export const retryWithExponentialBackoff = ( export const flatten = (task: Task>): Task => task.chain(identity) +/** + * Given a predicate, if it returns true, error the task with a given value. + * @param pred Run this on a successful task, return true to fail the task. + * @param error If the predicate succeeded, run this function to get the error result. + */ +export const failIf = ( + pred: (result: S) => boolean, + error: (result: S) => E2, + task: Task, +): Task => + task.chain(result => (pred(result) ? fail(error(result)) : of(result))) + /** * Create a new task. * @param computation A function which will be run when the task starts. @@ -963,6 +975,13 @@ export class Task implements PromiseLike { public flatten(this: Task>): Task { return flatten(this) } + + public failIf( + pred: (result: S) => boolean, + error: (result: S) => E2, + ): Task { + return failIf(pred, error, this) + } } /** diff --git a/src/Task/__tests__/failIf.spec.ts b/src/Task/__tests__/failIf.spec.ts new file mode 100644 index 00000000..e62c5ec5 --- /dev/null +++ b/src/Task/__tests__/failIf.spec.ts @@ -0,0 +1,31 @@ +import { of } from "../Task" + +describe("failIf", () => { + test("should fail with new error type", () => { + const resolve = jest.fn() + const reject = jest.fn() + + const lt5 = (v: number) => v < 5 + + of(4) + .failIf(lt5, v => `${v} < 5`) + .fork(reject, resolve) + + expect(resolve).not.toBeCalled() + expect(reject).toBeCalledWith("4 < 5") + }) + + test("should succeed if predicate fails", () => { + const resolve = jest.fn() + const reject = jest.fn() + + const lt5 = (v: number) => v < 5 + + of(10) + .failIf(lt5, v => `${v} < 5`) + .fork(reject, resolve) + + expect(reject).not.toBeCalled() + expect(resolve).toBeCalledWith(10) + }) +})