Files
skills/docs/foundation/data/validation/src/schemas/union/union.md
2026-05-29 08:20:56 +01:00

2.4 KiB

UnionSchema

(no submodules)

Purpose

UnionSchema validates that an input satisfies at least one of a list of member schemas. It short-circuits on the first successful parse, returning that result without checking remaining members. When all members fail, it aggregates all their issues into the ValidationError, giving the caller visibility into why each arm failed.

Features

  • Short-circuit success: first matching schema wins
  • All-failure aggregation: every arm's issues collected into one ValidationError
  • Empty union: always fails with VALIDATION.UNION.NO_MATCH

Usage: Basic Example

import { union, string, number } from "@suaveplan/validation";

const stringOrNumber = union([string(), number()]);
stringOrNumber.parse("hello"); // "hello"
stringOrNumber.parse(42); // 42
stringOrNumber.parse(true); // throws ValidationError

Usage: Advanced Example

import { union, literal, object, string } from "@suaveplan/validation";

// Discriminated union
const Event = union([
  object({ type: literal("created"), id: string() }),
  object({ type: literal("deleted"), id: string(), reason: string() }),
]);

Event.parse({ type: "created", id: "abc" });
// { type: "created", id: "abc" }

API Reference

union(schemas: AnySchema[]): UnionSchema

Factory accepting an array of member schemas.

_parse(input, ctx): unknown | INVALID

Iterates schemas in order. Returns the first non-INVALID result. On all-failure, pushes all collected issues to ctx.issues and returns INVALID. Empty union always adds a single VALIDATION.UNION.NO_MATCH issue.

Implementation Notes

  • Each arm runs with its own childCtx so its issues don't contaminate the parent context until the all-failure path is confirmed.
  • The order of schemas matters: place more specific schemas first to avoid false positives from permissive schemas like string().
  • The aggregated issue list can be long for wide unions; callers may want to use flatten() to extract meaningful field-level errors.

Parse Behaviour

z.union([a, b, c]) tries each member in order and returns the first success; all failures are aggregated into a ZodUnionError with per-member diagnostics so callers can show a useful error. For discriminated unions (a shared literal key across members), prefer z.discriminatedUnion("kind", [...]) which is faster and produces cleaner errors.