Hyperlinkv0.8.0-beta.28

Stream

Stream.catchReasonsconsteffect/Stream.ts:5653
<
  K extends Tags<E>,
  E,
  Cases extends {
    [RK in ReasonTags<ExtractTag<NoInfer<E>, K>>]+?: (
      reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
      error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
    ) => Stream<any, any, any>
  },
  A2 = unassigned,
  E2 = never,
  R2 = never
>(
  errorTag: K,
  cases: Cases,
  orElse?:
    | ((
        reason: ExcludeReason<
          ExtractTag<NoInfer<E>, K>,
          Extract<keyof Cases, string>
        >,
        error: OmitReason<
          ExtractTag<NoInfer<E>, K>,
          Extract<keyof Cases, string>
        >
      ) => Stream<A2, E2, R2>)
    | undefined
): <A, R>(
  self: Stream<A, E, R>
) => Stream<
  | A
  | Exclude<A2, unassigned>
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<infer A, any, any>
        ? A
        : never
    }[keyof Cases],
  | ExcludeTag<E, K>
  | E2
  | (A2 extends unassigned ? ExtractTag<E, K> : never)
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<any, infer E, any>
        ? E
        : never
    }[keyof Cases],
  | R
  | R2
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<any, any, infer R>
        ? R
        : never
    }[keyof Cases]
>
<
  A,
  E,
  R,
  K extends Tags<E>,
  Cases extends {
    [RK in ReasonTags<ExtractTag<E, K>>]+?: (
      reason: ExtractReason<ExtractTag<E, K>, RK>,
      error: NarrowReason<ExtractTag<E, K>, RK>
    ) => Stream<any, any, any>
  },
  A2 = unassigned,
  E2 = never,
  R2 = never
>(
  self: Stream<A, E, R>,
  errorTag: K,
  cases: Cases,
  orElse?:
    | ((
        reason: ExcludeReason<
          ExtractTag<NoInfer<E>, K>,
          Extract<keyof Cases, string>
        >,
        error: OmitReason<
          ExtractTag<NoInfer<E>, K>,
          Extract<keyof Cases, string>
        >
      ) => Stream<A2, E2, R2>)
    | undefined
): Stream<
  | A
  | Exclude<A2, unassigned>
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<infer A, any, any>
        ? A
        : never
    }[keyof Cases],
  | ExcludeTag<E, K>
  | E2
  | (A2 extends unassigned ? ExtractTag<E, K> : never)
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<any, infer E, any>
        ? E
        : never
    }[keyof Cases],
  | R
  | R2
  | {
      [RK in keyof Cases]: Cases[RK] extends (
        ...args: Array<any>
      ) => Stream<any, any, infer R>
        ? R
        : never
    }[keyof Cases]
>

Catches multiple reasons within a tagged error using an object of handlers.

Example (Catching tagged error reasons)

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.catchReasons("AiError", {
      RateLimitError: (reason) => Stream.succeed(`retry: ${reason.retryAfter}`),
      QuotaExceededError: (reason) => Stream.succeed(`quota: ${reason.limit}`)
    }),
    Stream.runCollect
  )
  yield* Console.log(values)
})

Effect.runPromise(program)
// Output: [ "retry: 60" ]
error handling
Source effect/Stream.ts:5653101 lines
export const catchReasons: {
  <
    K extends Tags<E>,
    E,
    Cases extends {
      [RK in ReasonTags<ExtractTag<NoInfer<E>, K>>]+?: (
        reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
        error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
      ) => Stream<any, any, any>
    },
    A2 = unassigned,
    E2 = never,
    R2 = never
  >(
    errorTag: K,
    cases: Cases,
    orElse?:
      | ((
        reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
        error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
      ) => Stream<A2, E2, R2>)
      | undefined
  ): <A, R>(self: Stream<A, E, R>) => Stream<
    | A
    | Exclude<A2, unassigned>
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<infer A, any, any> ? A : never
    }[keyof Cases],
    | ExcludeTag<E, K>
    | E2
    | (A2 extends unassigned ? ExtractTag<E, K> : never)
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<any, infer E, any> ? E : never
    }[keyof Cases],
    | R
    | R2
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<any, any, infer R> ? R : never
    }[keyof Cases]
  >
  <
    A,
    E,
    R,
    K extends Tags<E>,
    Cases extends {
      [RK in ReasonTags<ExtractTag<E, K>>]+?: (
        reason: ExtractReason<ExtractTag<E, K>, RK>,
        error: NarrowReason<ExtractTag<E, K>, RK>
      ) => Stream<any, any, any>
    },
    A2 = unassigned,
    E2 = never,
    R2 = never
  >(
    self: Stream<A, E, R>,
    errorTag: K,
    cases: Cases,
    orElse?:
      | ((
        reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
        error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
      ) => Stream<A2, E2, R2>)
      | undefined
  ): Stream<
    | A
    | Exclude<A2, unassigned>
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<infer A, any, any> ? A : never
    }[keyof Cases],
    | ExcludeTag<E, K>
    | E2
    | (A2 extends unassigned ? ExtractTag<E, K> : never)
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<any, infer E, any> ? E : never
    }[keyof Cases],
    | R
    | R2
    | {
      [RK in keyof Cases]: Cases[RK] extends (...args: Array<any>) => Stream<any, any, infer R> ? R : never
    }[keyof Cases]
  >
} = dual((args) => isStream(args[0]), (self, errorTag, cases, orElse) => {
  const handlers: Record<string, (reason: any, error: any) => Channel.Channel<any, any, any, any, any, any, any>> = {}
  for (const key of Object.keys(cases)) {
    const handler = (cases as any)[key]
    handlers[key] = (reason, error) => handler(reason, error).channel
  }
  const orElseHandler = orElse && ((reason: any, error: any) => orElse(reason, error).channel)
  return fromChannel(
    Channel.catchReasons(self.channel, errorTag as any, handlers as any, orElseHandler as any) as Channel.Channel<
      Arr.NonEmptyReadonlyArray<any>,
      any,
      void,
      unknown,
      unknown,
      unknown,
      any
    >
  ) as any
})