Hyperlinkv0.8.0-beta.28

Schema

Schema.TaggedUnionfunctioneffect/Schema.ts:6204
TaggedUnion<Cases>

Builds a discriminated union from a record of field sets, one per variant. Each key becomes the _tag literal and the value is passed to TaggedStruct. The result includes cases, guards, isAnyOf, and match utilities.

Example (Pattern matching a discriminated union)

import { Schema } from "effect"

const Shape = Schema.TaggedUnion({
  Circle: { radius: Schema.Number },
  Rectangle: { width: Schema.Number, height: Schema.Number }
})

// Pattern-match on a decoded value
const area = Shape.match({ _tag: "Circle", radius: 5 }, {
  Circle: (c) => Math.PI * c.radius ** 2,
  Rectangle: (r) => r.width * r.height
})
Source effect/Schema.ts:620467 lines
export interface TaggedUnion<Cases extends Record<string, Constraint>> extends
  BottomLazy<
    SchemaAST.Union<SchemaAST.Objects>,
    TaggedUnion<Cases>
  >
{
  readonly "Type": { [K in keyof Cases]: Cases[K]["Type"] }[keyof Cases]
  readonly "Encoded": { [K in keyof Cases]: Cases[K]["Encoded"] }[keyof Cases]
  readonly "DecodingServices": { [K in keyof Cases]: Cases[K]["DecodingServices"] }[keyof Cases]
  readonly "EncodingServices": { [K in keyof Cases]: Cases[K]["EncodingServices"] }[keyof Cases]
  readonly "~type.make.in": { [K in keyof Cases]: Cases[K]["~type.make"] }[keyof Cases]
  readonly "~type.make": { [K in keyof Cases]: Cases[K]["~type.make"] }[keyof Cases]
  readonly "Iso": { [K in keyof Cases]: Cases[K]["Type"] }[keyof Cases]
  readonly cases: Cases
  readonly isAnyOf: <const Keys>(
    keys: ReadonlyArray<Keys>
  ) => (value: Cases[keyof Cases]["Type"]) => value is Extract<Cases[keyof Cases]["Type"], { _tag: Keys }>
  readonly guards: { [K in keyof Cases]: (u: unknown) => u is Cases[K]["Type"] }
  readonly match: {
    <Output>(
      cases: { [K in keyof Cases]: (value: Cases[K]["Type"]) => Output }
    ): (value: Cases[keyof Cases]["Type"]) => Output
    <Output>(
      value: Cases[keyof Cases]["Type"],
      cases: { [K in keyof Cases]: (value: Cases[K]["Type"]) => Output }
    ): Output
  }
}

/**
 * Builds a discriminated union from a record of field sets, one per variant.
 * Each key becomes the `_tag` literal and the value is passed to {@link TaggedStruct}.
 * The result includes `cases`, `guards`, `isAnyOf`, and `match` utilities.
 *
 * **Example** (Pattern matching a discriminated union)
 *
 * ```ts
 * import { Schema } from "effect"
 *
 * const Shape = Schema.TaggedUnion({
 *   Circle: { radius: Schema.Number },
 *   Rectangle: { width: Schema.Number, height: Schema.Number }
 * })
 *
 * // Pattern-match on a decoded value
 * const area = Shape.match({ _tag: "Circle", radius: 5 }, {
 *   Circle: (c) => Math.PI * c.radius ** 2,
 *   Rectangle: (r) => r.width * r.height
 * })
 * ```
 *
 * @see {@link toTaggedUnion} to augment an existing union instead
 * @category constructors
 * @since 4.0.0
 */
export function TaggedUnion<const CasesByTag extends Record<string, Struct.Fields>>(
  casesByTag: CasesByTag
): TaggedUnion<{ readonly [K in keyof CasesByTag & string]: TaggedStruct<K, CasesByTag[K]> }> {
  const cases: any = {}
  const members: any = []
  for (const key of Object.keys(casesByTag)) {
    members.push(cases[key] = TaggedStruct(key, casesByTag[key]))
  }
  const union = Union(members)
  const { guards, isAnyOf, match } = toTaggedUnion("_tag")(union)
  return make(union.ast, { cases, isAnyOf, guards, match })
}