Skip to content

Discriminated unions in Zod #1

@nickrttn

Description

@nickrttn

We would like to use Zod to define schemas for our Robots, Assembly and Template constructs, and more to come. The schemas can then be used by our customers and us to validate and type these types of data and later on by us to build editor completions and linting in our user dashboard.

In order to do that correctly, we need two features in Zod that are currently missing:

  • the usage of intersections in discriminated unions
  • the nesting of discriminated unions in discriminated unions

Both have been reported/requested by other users in the Zod repo in colinhacks/zod#1075 and colinhacks/zod#1618

In this repo, the schema that is currently breaking in particular is the robotSchema, caused by the intersections here:

types/src/robots/index.ts

Lines 180 to 183 in cecd12c

videoConcatRobotSchema,
videoEncodeRobotSchema,
videoMergeRobotSchema,
videoSubtitleRobotSchema,

These four schemas are (should be) intersections of z.object and z.discriminatedUnion. They themselves are used in the robotSchema mentioned above, which is also a z.discriminatedUnion.

A simplified example of what we want to achieve type-wise is this:

type Robots =
  | { robot: "/upload/handle" }
  | {
      robot: "/s3/store"
      use: string
      key: string
      bucket: string
    }
  | ({ robot: "/video/encode"; use: string; preset: string; result?: boolean } & (
      | { ffmpeg_stack: "v3.3.3"; preset: "foo" }
      | { ffmpeg_stack: "v4.3.1"; preset: "foo" | "bar" }
    ))

type Assembly = {
  steps: Record<string, Robots & { result?: boolean }>
}

The discriminators here are robot and ffmpeg_stack (and we might have other discriminators nested in individual Robots as well). The /video/encode robot is an intersection of an object and a discriminated union.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions