Skip to content

Support @oneOf directive #1262

@azasorin-rss

Description

@azasorin-rss

The @oneOf directive allows for the union of inputs, and was recently merged into the GraphQL spec. It's also supported by the graphql code generator plugin and supported by the Envelop plugin system. (a good explanation of @oneOf directive is featured here)

Currently, the zod schema (and I assume other schemas) generated by this plugin do not match the type generated by graphql-code-generator.

Examples:

GraphQL Types

input AssignEventInput {
  targetType: String
  targetId: String
  assignedTo: String
  assignedBy: String
}

input PlaceholderEventInput {
  placeholder: String
}

input EventInput @oneOf {
  assignEvent: AssignEventInput
  placeholder: PlaceholderEventInput
}

Generated TypeScript Type

export type EventInput =
  { assignEvent: AssignEventInput; placeholder?: never; }
  |  { assignEvent?: never; placeholder: PlaceholderEventInput; };

Generated Zod (v4) Schema

export function EventInputSchema(): z.ZodObject<Properties<EventInput>> {
  return z.object({
    assignEvent: z.lazy(() => AssignEventInputSchema().nullish()),
    placeholder: z.lazy(() => PlaceholderEventInputSchema().nullish())
  })
}

This generated schema causes a compile error due to the mismatch between the generated EventInput type and the schema.

I think the generated schema should be something like this, but I'm not sure how to type the return of the EventInputSchema function.

  z.union([
    z.object({
      assignEvent: z.lazy(() => AssignEventInputSchema()),
      placeholder: z.never()
    }),
    z.object({
      assignEvent: z.never(),
      placeholder: z.lazy(() => PlaceholderEventInputSchema())
    })
  ]);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions