Skip to content

Commit

Permalink
Make Option.liftPredicate dual (#2957)
Browse files Browse the repository at this point in the history
  • Loading branch information
LaureRC authored and tim-smart committed Jun 20, 2024
1 parent 868f604 commit 7fb15fe
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-turkeys-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Make Option.liftPredicate dual
26 changes: 26 additions & 0 deletions packages/effect/dtslint/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare const predicateNumbersOrStrings: Predicate.Predicate<number | string>
// $ExpectType Option<string>
pipe(pimitiveNumerOrString, Option.liftPredicate(Predicate.isString))

// $ExpectType Option<number>
pipe(
pimitiveNumerOrString,
Option.liftPredicate(
Expand All @@ -41,6 +42,31 @@ pipe(
)
)

// $ExpectType Option<string>
Option.liftPredicate(pimitiveNumerOrString, Predicate.isString)

// $ExpectType Option<number>
Option.liftPredicate(
pimitiveNumerOrString,
(
n // $ExpectType string | number
): n is number => typeof n === "number"
)

// $ExpectType Option<string | number>
Option.liftPredicate(pimitiveNumerOrString, predicateNumbersOrStrings)

// $ExpectType Option<number>
Option.liftPredicate(pimitiveNumber, predicateNumbersOrStrings)

// $ExpectType Option<number>
Option.liftPredicate(
pimitiveNumber,
(
_n // $ExpectType number
) => true
)

// -------------------------------------------------------------------------------------
// getOrElse
// -------------------------------------------------------------------------------------
Expand Down
13 changes: 12 additions & 1 deletion packages/effect/src/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,18 @@ export const lift2 = <A, B, C>(f: (a: A, b: B) => C): {
export const liftPredicate: { // Note: I intentionally avoid using the NoInfer pattern here.
<A, B extends A>(refinement: Refinement<A, B>): (a: A) => Option<B>
<B extends A, A = B>(predicate: Predicate<A>): (b: B) => Option<B>
} = <B extends A, A = B>(predicate: Predicate<A>) => (b: B): Option<B> => predicate(b) ? some(b) : none()
<A, B extends A>(
self: A,
refinement: Refinement<A, B>
): Option<B>
<B extends A, A = B>(
self: B,
predicate: Predicate<A>
): Option<B>
} = dual(
2,
<B extends A, A = B>(b: B, predicate: Predicate<A>): Option<B> => predicate(b) ? some(b) : none()
)

/**
* Returns a function that checks if a `Option` contains a given value using a provided `isEquivalent` function.
Expand Down
15 changes: 9 additions & 6 deletions packages/effect/test/Option.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down

0 comments on commit 7fb15fe

Please sign in to comment.