Hyperlinkv0.8.0-beta.28

Stream

Stream.catchTagsconsteffect/Stream.ts:5390
<
  E,
  Cases extends E extends { _tag: string }
    ? {
        [K in E["_tag"]]+?: (
          error: Extract<E, { _tag: K }>
        ) => Stream<any, any, any>
      }
    : {},
  A2 = unassigned,
  E2 = never,
  R2 = never
>(
  cases: Cases,
  orElse?:
    | ((e: Exclude<E, { _tag: keyof Cases }>) => Stream<A2, E2, R2>)
    | undefined
): <A, R>(
  self: Stream<A, E, R>
) => Stream<
  | A
  | Exclude<A2, unassigned>
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<infer A, any, any>
        ? A
        : never
    }[keyof Cases],
  | E2
  | (A2 extends unassigned ? Exclude<E, { _tag: keyof Cases }> : never)
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<any, infer E, any>
        ? E
        : never
    }[keyof Cases],
  | R
  | R2
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<any, any, infer R>
        ? R
        : never
    }[keyof Cases]
>
<
  R,
  E,
  A,
  Cases extends E extends { _tag: string }
    ? {
        [K in E["_tag"]]+?: (
          error: Extract<E, { _tag: K }>
        ) => Stream<any, any, any>
      }
    : {},
  A2 = unassigned,
  E2 = never,
  R2 = never
>(
  self: Stream<A, E, R>,
  cases: Cases,
  orElse?:
    | ((e: Exclude<E, { _tag: keyof Cases }>) => Stream<A2, E2, R2>)
    | undefined
): Stream<
  | A
  | Exclude<A2, unassigned>
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<infer A, any, any>
        ? A
        : never
    }[keyof Cases],
  | E2
  | (A2 extends unassigned ? Exclude<E, { _tag: keyof Cases }> : never)
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<any, infer E, any>
        ? E
        : never
    }[keyof Cases],
  | R
  | R2
  | {
      [K in keyof Cases]: Cases[K] extends (
        ...args: Array<any>
      ) => Stream<any, any, infer R>
        ? R
        : never
    }[keyof Cases]
>

Switches to a recovery stream based on matching _tag handlers.

Example (Catching tagged failures with handlers)

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

class NotFound {
  readonly _tag = "NotFound"
  constructor(readonly resource: string) {}
}

class Unauthorized {
  readonly _tag = "Unauthorized"
  constructor(readonly user: string) {}
}

const stream = Stream.fail(new NotFound("profile"))

const program = Effect.gen(function* () {
  const result = yield* stream.pipe(
    Stream.catchTags({
      NotFound: () => Stream.succeed("fallback"),
      Unauthorized: () => Stream.succeed("login")
    }),
    Stream.runCollect
  )
  yield* Console.log(result)
})

// Output: [ "fallback" ]
error handling
Source effect/Stream.ts:539076 lines
export const catchTags: {
  <
    E,
    Cases extends (E extends { _tag: string } ? {
        [K in E["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Stream<any, any, any>
      } :
      {}),
    A2 = unassigned,
    E2 = never,
    R2 = never
  >(
    cases: Cases,
    orElse?: ((e: Exclude<E, { _tag: keyof Cases }>) => Stream<A2, E2, R2>) | undefined
  ): <A, R>(self: Stream<A, E, R>) => Stream<
    | A
    | Exclude<A2, unassigned>
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<infer A, any, any>) ? A : never
    }[keyof Cases],
    | E2
    | (A2 extends unassigned ? Exclude<E, { _tag: keyof Cases }> : never)
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<any, infer E, any>) ? E : never
    }[keyof Cases],
    | R
    | R2
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<any, any, infer R>) ? R : never
    }[keyof Cases]
  >
  <
    R,
    E,
    A,
    Cases extends (E extends { _tag: string } ? {
        [K in E["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Stream<any, any, any>
      } :
      {}),
    A2 = unassigned,
    E2 = never,
    R2 = never
  >(
    self: Stream<A, E, R>,
    cases: Cases,
    orElse?: ((e: Exclude<E, { _tag: keyof Cases }>) => Stream<A2, E2, R2>) | undefined
  ): Stream<
    | A
    | Exclude<A2, unassigned>
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<infer A, any, any>) ? A : never
    }[keyof Cases],
    | E2
    | (A2 extends unassigned ? Exclude<E, { _tag: keyof Cases }> : never)
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<any, infer E, any>) ? E : never
    }[keyof Cases],
    | R
    | R2
    | {
      [K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Stream<any, any, infer R>) ? R : never
    }[keyof Cases]
  >
} = dual((args) => isStream(args[0]), (self, cases, orElse) => {
  let keys: Array<string>
  return catchFilter(
    self,
    (e: any) => {
      keys ??= Object.keys(cases)
      return hasProperty(e, "_tag") && isString(e["_tag"]) && keys.includes(e["_tag"])
        ? Result.succeed(e)
        : Result.fail(e)
    },
    (e: any) => cases[e["_tag"] as string](e),
    orElse
  )
})