Hyperlinkv0.8.0-beta.28

Iterable

Iterable.filterMapconsteffect/Iterable.ts:1660
<A, B, X>(f: (input: A, i: number) => Result<B, X>): (
  self: Iterable<A>
) => Iterable<B>
<A, B, X>(
  self: Iterable<A>,
  f: (input: A, i: number) => Result<B, X>
): Iterable<B>

Transforms elements of an iterable using a function that returns a Result, keeping only successful values.

Details

This combines mapping and filtering in a single operation. The function is applied to each element, and only elements that result in Result.succeed are included in the result.

Example (Filtering and transforming Result values)

import { Iterable, Result } from "effect"

// Parse strings to numbers, keeping only valid ones
const strings = ["1", "2", "invalid", "4", "not-a-number"]
const numbers = Iterable.filterMap(strings, (s) => {
  const num = parseInt(s)
  return isNaN(num) ? Result.failVoid : Result.succeed(num)
})
console.log(Array.from(numbers)) // [1, 2, 4]

// Extract specific properties from objects
const users = [
  { name: "Alice", age: 25, email: "[email protected]" },
  { name: "Bob", age: 17, email: undefined },
  { name: "Charlie", age: 30, email: "[email protected]" },
  { name: "David", age: 16, email: undefined }
]
const adultEmails = Iterable.filterMap(
  users,
  (user) =>
    user.age >= 18 && user.email ? Result.succeed(user.email) : Result.failVoid
)
console.log(Array.from(adultEmails)) // ["[email protected]", "[email protected]"]

// Use index in transformation
const items = ["a", "b", "c", "d", "e"]
const evenIndexItems = Iterable.filterMap(
  items,
  (item, i) => i % 2 === 0 ? Result.succeed(`${i}: ${item}`) : Result.failVoid
)
console.log(Array.from(evenIndexItems)) // ["0: a", "2: c", "4: e"]
filtering
export const filterMap: {
  <A, B, X>(f: (input: A, i: number) => Result<B, X>): (self: Iterable<A>) => Iterable<B>
  <A, B, X>(self: Iterable<A>, f: (input: A, i: number) => Result<B, X>): Iterable<B>
} = dual(
  2,
  <A, B, X>(self: Iterable<A>, f: (input: A, i: number) => Result<B, X>): Iterable<B> => ({
    [Symbol.iterator]() {
      const iterator = self[Symbol.iterator]()
      let i = 0
      return {
        next() {
          let result = iterator.next()
          while (!result.done) {
            const next = f(result.value, i++)
            if (R.isSuccess(next)) {
              return { done: false, value: next.success }
            }
            result = iterator.next()
          }
          return { done: true, value: undefined }
        }
      }
    }
  })
)
Referenced by 3 symbols