DEV Community

Alessandro Maclaine
Alessandro Maclaine

Posted on

Filtering Options in Effect-TS: A Practical Guide

Effect-TS provides various methods to filter values inside an Option, allowing you to apply transformations, predicates, or checks on the optional value. These functions help ensure that only relevant data is retained while discarding None values or those that don't meet specified conditions. In this article, we'll explore four key functions for filtering Options: O.partitionMap, O.filterMap, O.filter, and O.exists.

Example 1: Partitioning an Option with O.partitionMap

Concept

The O.partitionMap function allows you to partition an Option into a tuple of two Options based on a mapping function that returns an Either. The Either.left values are partitioned into the first Option, while Either.right values go into the second Option. If the original Option is None, both partitions are None.

Code

function filtering_ex01() {
  const some = O.some(1); // Create an Option containing the value 1
  const none = O.none(); // Create an Option representing no value
  const toEither = (n: number) => (n % 2 === 0 ? E.left(n) : E.right(n));

  console.log(pipe(some, O.partitionMap(toEither))); // Output: [None, Some(1)] (1 is odd, so it goes to the right)
  console.log(pipe(none, O.partitionMap(toEither))); // Output: [None, None] (since the Option is None)
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • pipe(some, O.partitionMap(toEither)): Since 1 is odd, the toEither function returns E.right(1), placing 1 in the second Option, resulting in [None, Some(1)].
  • pipe(none, O.partitionMap(toEither)): Since the original Option is None, both partitions are None, resulting in [None, None].

This function is useful when you need to apply a mapping that categorizes values, while separating them into two groups—those that satisfy a condition and those that don't.

Example 2: Mapping and Filtering with O.filterMap

Concept

The O.filterMap function applies a transformation function to the value inside an Option. If the function returns Some, the value is retained; if it returns None, the value is filtered out. If the original Option is None, the result remains None.

Code

function filtering_ex02() {
  const some = O.some(1); // Create an Option containing the value 1
  const none = O.none(); // Create an Option representing no value
  const toEven = (n: number) => (n % 2 === 0 ? O.some(n) : O.none());

  console.log(pipe(some, O.filterMap(toEven))); // Output: None (since 1 is not even)
  console.log(pipe(O.some(2), O.filterMap(toEven))); // Output: Some(2) (since 2 is even)
  console.log(pipe(none, O.filterMap(toEven))); // Output: None (since the original Option is None)
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • pipe(some, O.filterMap(toEven)): Since 1 is not even, the toEven function returns None, and the result is None.
  • pipe(O.some(2), O.filterMap(toEven)): The value 2 is even, so the toEven function returns Some(2), and the result is Some(2).
  • pipe(none, O.filterMap(toEven)): Since the original Option is None, the result remains None.

This function is helpful when you want to both transform and filter the value inside an Option based on specific conditions.

Example 3: Filtering an Option with a Predicate using O.filter

Concept

The O.filter function checks if the value inside an Option satisfies a given predicate. If the predicate is satisfied, it returns the original Option; otherwise, it returns None. If the original Option is None, it remains None.

Code

function filtering_ex03() {
  const some = O.some(1); // Create an Option containing the value 1
  const none = O.none(); // Create an Option representing no value
  const isEven = (n: number) => n % 2 === 0;

  console.log(pipe(some, O.filter(isEven))); // Output: None (since 1 is not even)
  console.log(pipe(O.some(2), O.filter(isEven))); // Output: Some(2) (since 2 is even)
  console.log(pipe(none, O.filter(isEven))); // Output: None (since the original Option is None)
}
Enter fullscreen mode Exit fullscreen mode

Example 4: Checking a Predicate with O.exists

Concept

The O.exists function checks if a value inside an Option satisfies a predicate, returning true if it does, and false if it doesn't. If the Option is None, it returns false.

Code

function filtering_ex04() {
  const some = O.some(1); // Create an Option containing the value 1
  const none = O.none(); // Create an Option representing no value
  const isEven = (n: number) => n % 2 === 0;

  console.log(pipe(some, O.exists(isEven))); // Output: false (since 1 is not even)
  console.log(pipe(O.some(2), O.exists(isEven))); // Output: true (since 2 is even)
  console.log(pipe(none, O.exists(isEven))); // Output: false (since the original Option is None)
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • pipe(some, O.exists(isEven)): Since 1 is not even, the predicate is not satisfied, so the result is false.
  • pipe(O.some(2), O.exists(isEven)): The value 2 satisfies the predicate, so the result is true.
  • pipe(none, O.exists(isEven)): Since the Option is None, the result is false.

This function is useful when you need a quick check to determine if the value inside an Option satisfies a condition without transforming or filtering the Option itself.

Conclusion

Filtering Options in Effect-TS allows for flexible handling of optional values based on conditions or transformations. Whether you're partitioning values with O.partitionMap, applying transformations with O.filterMap, checking predicates with O.filter, or simply verifying conditions with O.exists, these tools provide robust methods for controlling how Options are handled. By using these functions, you can manage optional data efficiently, ensuring only the relevant values are kept or acted upon.

Top comments (0)