Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pnpm-lock.yaml
!src/pages/blog/2024-08-15-graphql-local-initiative.mdx
!src/pages/community/foundation/community-grant.mdx
!src/pages/blog/2025-06-01-graphiql-4/index.mdx
!src/pages/blog/2025-06-19-multioption-inputs-with-oneof/index.mdx
*.jpg

scripts/sync-sched/*.json
Expand Down
106 changes: 106 additions & 0 deletions src/pages/blog/2025-06-19-multioption-inputs-with-oneof/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
title: Safer Multi-option Inputs with `@oneOf`
tags: [announcements, spec]
date: 2025-06-19
byline: Benjie Gillam
---

We’re excited to announce
**[OneOf Input Objects](https://github.com/graphql/graphql-spec/pull/825)** has
landed in the GraphQL specification! This enhancement solves a long-standing
challenge in API design: how to allow users to provide **exactly one** of
several possible options as input, in a clean and enforceable way. This feature
is a small change that packs a big return for developers building modern digital
products with GraphQL.

## Simplifying entrypoints

Most GraphQL queries start at a single node, and traverse the data graph from
there. But often, there is more than one way of locating that node; for example
you might find a user by their ID, email address, or username. Traditionally,
that meant multiple root-level fields:

```graphql
type Query {
user(id: ID!): User
userByEmail(email: String!): User
userByUsername(username: String!): User
}
```

_(An alternative approach was a less-than-type-safe field presenting all the
options along with custom runtime validation to enforce the constraints. Either
way, neither solution was ideal.)_

With `@oneOf`, you can now consolidate those options into a single,
user-friendly input which ensures users supply _exactly one_ input field, the
value of which must not be null. The result: a user-friendly schema with fewer
root-level fields and without sacrificing type safety:

```graphql
input UserBy @oneOf {
id: ID
email: String
username: String
}

type Query {
user(by: UserBy!): User
}
```

## Input polymorphism

Of course, `@oneOf`'s use isn't limited to simple scalars — it can also be used
to choose between multiple complex input types, allowing for polymorphism in
GraphQL inputs.

Imagine you were building a user-friendly blogging website, and each post is
made up of elements — paragraphs, image galleries, block quotes, code blocks,
and the like. Each of these elements come with their own set of (potentially
overlapping) attributes, and you want to feed a list of them into your mutation.
With @oneOf you can do so in a type safe manner:

```graphql
type Mutation {
createPost(elements: [PostElementInput]): Post
}
input PostElementInput @oneOf {
paragraph: ParagraphInput
blockquote: BlockQuoteInput
gallery: GalleryInput
}
input ParagraphInput {
text: String!
}
input BlockQuoteInput {
text: String!
attribution: String
attributionUrl: String
}
input GalleryInput {
imageUrls: [String!]!
caption: String
attribution: String
}
```

## What Makes `@oneOf` The Right Solution?

- **Backward Compatible**: Existing tools, queries and clients still work,
meaning no major overhauls are required. Existing clients can even use oneOf
inputs without updating; just be careful to always supply exactly one value!
- **Minimal Complexity**: This feature introduces only a small change to the
existing type system, but delivers very significant benefits.
- **Type-Safe Input Polymorphism**: Offers a safe and scalable way to accept a
variety of inputs under a single structure—something previously hard to
achieve in GraphQL.
- **Now part of the GraphQL standard:** Several GraphQL implementations
including Ruby, Java, JavaScript and .NET already ship `@oneOf` as a stable
feature

## The Bottom Line

`@oneOf` allows for more expressive, capable, and less overwhelming schemas,
helping technical teams to move faster with increased safety. It’s simple and
easy to implement, try it today!