From 2bdd7131207c1fc9de14f18d8eecb46ceb115b2f Mon Sep 17 00:00:00 2001 From: Laure Retru-Chavastel Date: Wed, 12 Jun 2024 03:10:29 +0200 Subject: [PATCH] Make `Option.liftPredicate` dual (#2957) --- .changeset/fair-turkeys-float.md | 5 +++++ packages/effect/dtslint/Option.ts | 26 ++++++++++++++++++++++++++ packages/effect/src/Option.ts | 13 ++++++++++++- packages/effect/test/Option.test.ts | 15 +++++++++------ 4 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 .changeset/fair-turkeys-float.md diff --git a/.changeset/fair-turkeys-float.md b/.changeset/fair-turkeys-float.md new file mode 100644 index 00000000000..4ae79575d87 --- /dev/null +++ b/.changeset/fair-turkeys-float.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +Make Option.liftPredicate dual diff --git a/packages/effect/dtslint/Option.ts b/packages/effect/dtslint/Option.ts index a0e9863d046..ce2b032704b 100644 --- a/packages/effect/dtslint/Option.ts +++ b/packages/effect/dtslint/Option.ts @@ -16,6 +16,7 @@ declare const predicateNumbersOrStrings: Predicate.Predicate // $ExpectType Option pipe(pimitiveNumerOrString, Option.liftPredicate(Predicate.isString)) +// $ExpectType Option pipe( pimitiveNumerOrString, Option.liftPredicate( @@ -41,6 +42,31 @@ pipe( ) ) +// $ExpectType Option +Option.liftPredicate(pimitiveNumerOrString, Predicate.isString) + +// $ExpectType Option +Option.liftPredicate( + pimitiveNumerOrString, + ( + n // $ExpectType string | number + ): n is number => typeof n === "number" +) + +// $ExpectType Option +Option.liftPredicate(pimitiveNumerOrString, predicateNumbersOrStrings) + +// $ExpectType Option +Option.liftPredicate(pimitiveNumber, predicateNumbersOrStrings) + +// $ExpectType Option +Option.liftPredicate( + pimitiveNumber, + ( + _n // $ExpectType number + ) => true +) + // ------------------------------------------------------------------------------------- // getOrElse // ------------------------------------------------------------------------------------- diff --git a/packages/effect/src/Option.ts b/packages/effect/src/Option.ts index 3d77e447310..01de0073f0a 100644 --- a/packages/effect/src/Option.ts +++ b/packages/effect/src/Option.ts @@ -1115,7 +1115,18 @@ export const lift2 = (f: (a: A, b: B) => C): { export const liftPredicate: { // Note: I intentionally avoid using the NoInfer pattern here. (refinement: Refinement): (a: A) => Option (predicate: Predicate): (b: B) => Option -} = (predicate: Predicate) => (b: B): Option => predicate(b) ? some(b) : none() + ( + self: A, + refinement: Refinement + ): Option + ( + self: B, + predicate: Predicate + ): Option +} = dual( + 2, + (b: B, predicate: Predicate): Option => predicate(b) ? some(b) : none() +) /** * Returns a function that checks if a `Option` contains a given value using a provided `isEquivalent` function. diff --git a/packages/effect/test/Option.test.ts b/packages/effect/test/Option.test.ts index 4ecb0088af0..23f1f6acd7a 100644 --- a/packages/effect/test/Option.test.ts +++ b/packages/effect/test/Option.test.ts @@ -350,14 +350,17 @@ describe("Option", () => { }) it("liftPredicate", () => { - const f = Option.liftPredicate(p) - Util.deepStrictEqual(f(1), Option.none()) - Util.deepStrictEqual(f(3), Option.some(3)) + Util.deepStrictEqual(pipe(1, Option.liftPredicate(p)), Option.none()) + Util.deepStrictEqual(pipe(3, Option.liftPredicate(p)), Option.some(3)) + Util.deepStrictEqual(Option.liftPredicate(1, p), Option.none()) + Util.deepStrictEqual(Option.liftPredicate(3, p), Option.some(3)) type Direction = "asc" | "desc" - const parseDirection = Option.liftPredicate((s: string): s is Direction => s === "asc" || s === "desc") - Util.deepStrictEqual(parseDirection("asc"), Option.some("asc")) - Util.deepStrictEqual(parseDirection("foo"), Option.none()) + const isDirection = (s: string): s is Direction => s === "asc" || s === "desc" + Util.deepStrictEqual(pipe("asc", Option.liftPredicate(isDirection)), Option.some("asc")) + Util.deepStrictEqual(pipe("foo", Option.liftPredicate(isDirection)), Option.none()) + Util.deepStrictEqual(Option.liftPredicate("asc", isDirection), Option.some("asc")) + Util.deepStrictEqual(Option.liftPredicate("foo", isDirection), Option.none()) }) it("containsWith", () => {