Hyperlinkv0.8.0-beta.28

Stream

Stream.catchReasonconsteffect/Stream.ts:5517
<
  K extends Tags<E>,
  E,
  RK extends ReasonTags<ExtractTag<NoInfer<E>, K>>,
  A2,
  E2,
  R2,
  A3 = unassigned,
  E3 = never,
  R3 = never
>(
  errorTag: K,
  reasonTag: RK,
  f: (
    reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
    error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
  ) => Stream<A2, E2, R2>,
  orElse?:
    | ((
        reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, RK>,
        error: OmitReason<ExtractTag<NoInfer<E>, K>, RK>
      ) => Stream<A3, E3, R3>)
    | undefined
): <A, R>(
  self: Stream<A, E, R>
) => Stream<
  A | A2 | Exclude<A3, unassigned>,
  | ExcludeTag<E, K>
  | E2
  | E3
  | (A3 extends unassigned ? ExtractTag<E, K> : never),
  R | R2 | R3
>
<
  A,
  E,
  R,
  K extends Tags<E>,
  RK extends ReasonTags<ExtractTag<E, K>>,
  A2,
  E2,
  R2,
  A3 = unassigned,
  E3 = never,
  R3 = never
>(
  self: Stream<A, E, R>,
  errorTag: K,
  reasonTag: RK,
  f: (
    reason: ExtractReason<ExtractTag<E, K>, RK>,
    error: NarrowReason<ExtractTag<E, K>, RK>
  ) => Stream<A2, E2, R2>,
  orElse?:
    | ((
        reason: ExcludeReason<ExtractTag<E, K>, RK>,
        error: OmitReason<ExtractTag<E, K>, RK>
      ) => Stream<A3, E3, R3>)
    | undefined
): Stream<
  A | A2 | Exclude<A3, unassigned>,
  | ExcludeTag<E, K>
  | E2
  | E3
  | (A3 extends unassigned ? ExtractTag<E, K> : never),
  R | R2 | R3
>

Catches a specific reason within a tagged error.

When to use

Use to handle nested error causes without removing the parent error from the error channel.

Details

The handler receives the unwrapped reason.

Example (Catching a tagged error reason)

import { Console, Data, Effect, Stream } from "effect"

class RateLimitError extends Data.TaggedError("RateLimitError")<{
  retryAfter: number
}> {}

class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{
  limit: number
}> {}

class AiError extends Data.TaggedError("AiError")<{
  reason: RateLimitError | QuotaExceededError
}> {}

const stream = Stream.fail(
  new AiError({ reason: new RateLimitError({ retryAfter: 60 }) })
)

const program = Effect.gen(function*() {
  const values = yield* stream.pipe(
    Stream.catchReason("AiError", "RateLimitError", (reason) =>
      Stream.succeed(`retry: ${reason.retryAfter}`)
    ),
    Stream.runCollect
  )
  yield* Console.log(values)
})

Effect.runPromise(program)
// Output: [ "retry: 60" ]
error handling
Source effect/Stream.ts:551793 lines
export const catchReason: {
  <
    K extends Tags<E>,
    E,
    RK extends ReasonTags<ExtractTag<NoInfer<E>, K>>,
    A2,
    E2,
    R2,
    A3 = unassigned,
    E3 = never,
    R3 = never
  >(
    errorTag: K,
    reasonTag: RK,
    f: (
      reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
      error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
    ) => Stream<A2, E2, R2>,
    orElse?:
      | ((
        reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, RK>,
        error: OmitReason<ExtractTag<NoInfer<E>, K>, RK>
      ) => Stream<A3, E3, R3>)
      | undefined
  ): <A, R>(
    self: Stream<A, E, R>
  ) => Stream<
    A | A2 | Exclude<A3, unassigned>,
    ExcludeTag<E, K> | E2 | E3 | (A3 extends unassigned ? ExtractTag<E, K> : never),
    R | R2 | R3
  >
  <
    A,
    E,
    R,
    K extends Tags<E>,
    RK extends ReasonTags<ExtractTag<E, K>>,
    A2,
    E2,
    R2,
    A3 = unassigned,
    E3 = never,
    R3 = never
  >(
    self: Stream<A, E, R>,
    errorTag: K,
    reasonTag: RK,
    f: (reason: ExtractReason<ExtractTag<E, K>, RK>, error: NarrowReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
    orElse?:
      | ((reason: ExcludeReason<ExtractTag<E, K>, RK>, error: OmitReason<ExtractTag<E, K>, RK>) => Stream<A3, E3, R3>)
      | undefined
  ): Stream<
    A | A2 | Exclude<A3, unassigned>,
    ExcludeTag<E, K> | E2 | E3 | (A3 extends unassigned ? ExtractTag<E, K> : never),
    R | R2 | R3
  >
} = dual(
  (args) => isStream(args[0]),
  <
    A,
    E,
    R,
    K extends Tags<E>,
    RK extends ReasonTags<ExtractTag<E, K>>,
    A2,
    E2,
    R2,
    A3 = unassigned,
    E3 = never,
    R3 = never
  >(
    self: Stream<A, E, R>,
    errorTag: K,
    reasonTag: RK,
    f: (reason: ExtractReason<ExtractTag<E, K>, RK>, error: NarrowReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
    orElse?:
      | ((reason: ExcludeReason<ExtractTag<E, K>, RK>, error: OmitReason<ExtractTag<E, K>, RK>) => Stream<A3, E3, R3>)
      | undefined
  ): Stream<
    A | A2 | Exclude<A3, unassigned>,
    ExcludeTag<E, K> | E2 | E3 | (A3 extends unassigned ? ExtractTag<E, K> : never),
    R | R2 | R3
  > =>
    fromChannel(
      Channel.catchReason(
        toChannel(self),
        errorTag,
        reasonTag,
        (reason, error) => f(reason, error).channel,
        orElse && ((reason, error) => orElse(reason, error).channel)
      )
    ) as any
)