PageSourceSearch

https://graphql.org/_next/static/chunks/pages/blog/2025-09-04-mult…ption-inputs-with-oneof-07d08b3e030604c4.js

js graphql.org collected 2026-10-01 07:22:12 UTC 22,360 bytes, 1 lines download raw bytes

1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6011],{92148:function(i,s,e){(window.__NEXT_P=window.__NEXT_P||[]).push(["/blog/2025-09-04-multioption-inputs-with-oneof",function(){return e(48138)}])},48138:function(i,s,e){"use strict";e.r(s),e.d(s,{useTOC:function(){return r}});var n=e(52676),h=e(92937),l=e(45043),t=e(79428),a=e(41751);function r(i){let s={code:"code",...(0,t.a)()};return[{value:"Simplifying entrypoints",id:"simplifying-entrypoints",depth:2},{value:"Input polymorphism",id:"input-polymorphism",depth:2},{value:(0,n.jsxs)(n.Fragment,{children:["What makes ",(0,n.jsx)(s.code,{children:"@oneOf"})," the right solution?"]}),id:"what-makes-oneof-the-right-solution",depth:2},{value:"Availability",id:"availability",depth:2},{value:"The bottom line",id:"the-bottom-line",depth:2}]}s.default=(0,h.c)(function(i){let{toc:s=r(i)}=i,e={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",span:"span",strong:"strong",ul:"ul",...(0,t.a)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(e.p,{children:["We’re excited to announce ",(0,n.jsx)(e.strong,{children:(0,n.jsx)(e.a,{href:"https://spec.graphql.org/September2025/#sec-OneOf-Input-Objects",children:"OneOf Input\nObjects"})})," has\nlanded in the GraphQL specification! This enhancement solves a long-standing\nchallenge in API design: how to allow users to provide ",(0,n.jsx)(e.strong,{children:"exactly one"})," of\nseveral possible options as input, in a clean and enforceable way. This feature\nis a ",(0,n.jsx)(e.a,{href:"https://github.com/graphql/graphql-spec/pull/825",children:"small change"})," that packs\na big return for developers building modern digital products with GraphQL."]}),"\n",(0,n.jsx)(e.h2,{id:s[0].id,children:s[0].value}),"\n",(0,n.jsx)(e.p,{children:"Most GraphQL queries start at a single node, and traverse the data graph from\nthere. But often, there is more than one way of locating that node; for example\nyou might find a user by their ID, email address, or username. Traditionally,\nthat meant multiple root-level fields:"}),"\n",(0,n.jsx)(e.pre,{icon:a.Wo,tabIndex:"0","data-language":"graphql","data-word-wrap":"",children:(0,n.jsxs)(e.code,{children:[(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#990069","--shiki-dark":"#C2F653"},children:"type"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" Query"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  user"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"("}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:"id"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" ID"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:")"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" User"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  userByEmail"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"("}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:"email"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:")"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" User"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"}
1,children:"  userByUsername"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"("}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:"username"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:")"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" User"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})})]})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.em,{children:"(An alternative approach was a less-than-type-safe field presenting all the\noptions along with custom runtime validation to enforce the constraints. Either\nway, neither solution was ideal.)"})}),"\n",(0,n.jsxs)(e.p,{children:["With ",(0,n.jsx)(e.code,{children:"@oneOf"}),", you can now consolidate those options into a single,\nuser-friendly input which ensures users supply ",(0,n.jsx)(e.em,{children:"exactly one"})," input field, the\nvalue of which must not be null. The result: a user-friendly schema with fewer\nroot-level fields and without sacrificing type safety:"]}),"\n",(0,n.jsx)(e.pre,{icon:a.Wo,tabIndex:"0","data-language":"graphql","data-word-wrap":"",children:(0,n.jsxs)(e.code,{children:[(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#C2F653"},children:"input"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" UserBy"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:" @oneOf"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  id"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" ID"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  email"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  username"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})}),"\n",(0,n.jsx)(e.span,{children:" "}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#990069","--shiki-dark":"#C2F653"},children:"type"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" Query"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  user"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"("}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:"by"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" UserBy"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:")"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" User"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})})]})}),"\n",(0,n.jsx)(e.h2,{id:s[1].id,children:s[1].value}),"\n",(0,n.jsxs)(e.p,{children:["Of course, ",(0,n.jsx)(e.code,{children:"@oneOf"}),"’s use isn’t limited to simple scalars — it can also be used\nto choose between multiple complex input types, allowing for polymorphism in\nGraphQL inputs."]}),"\n",(0,n.jsx)(e.p,{children:"Imagine you were building a user-friendly blogging website, and each post is\nmade up of elements — paragraphs, image galleries, block quotes, code blocks,\nand the like. Each of these elements come with their own set of (potentially\noverlapping) attributes, and you want to feed a list of them into your mutation.\nWith @oneOf you can do so in a type safe manner:"}),"\n",(0,n.jsx)(e.pre,{icon:a.Wo,tabIndex:"0","data-language":"graphql","data-word-wrap":"",children:(0,n.jsxs)(e.code,{children:[(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#990069","--shiki-dark":"#C2F653"},children:"type"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" Mutation"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  createPost"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"("}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:"elements"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:" ["}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:"PostElementInput"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"])"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" Post"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#C2F653"},children:"input"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" PostElementInput"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#0E0F0B","--shiki-dark":"#F3F4F0"},children:" @oneOf"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  paragraph"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" ParagraphInput"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  blockquote"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" BlockQuoteInput"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  gallery"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" GalleryInput"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#C2F653"},children:"input"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" ParagraphInput"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  text"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#C2F653"},children:"input"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" BlockQuoteInput"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  text"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  attribution"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  attributionUrl"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#C2F653"},children:"input"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" GalleryInput"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:" {"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  imageUrls"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:" ["}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:"String"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#24292EFF","--shiki-dark":"#CFD3C5"},children:"]"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#ECFAD1"},children:"!"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"}
1,children:"  caption"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsxs)(e.span,{children:[(0,n.jsx)(e.span,{style:{"--shiki-light":"#E10198","--shiki-dark":"#DBF6A2"},children:"  attribution"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:":"}),(0,n.jsx)(e.span,{style:{"--shiki-light":"#1976D2","--shiki-dark":"#FF99E0"},children:" String"})]}),"\n",(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{style:{"--shiki-light":"#6E7557","--shiki-dark":"#6E7557"},children:"}"})})]})}),"\n",(0,n.jsx)(e.h2,{id:s[2].id,children:s[2].value}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:"Backward Compatible"}),": Existing tools, queries and clients still work,\nmeaning no major overhauls are required. Existing clients can even use oneOf\ninputs without updating; just be careful to always supply exactly one value!"]}),"\n",(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:"Minimal Complexity"}),": This feature introduces only a small change to the\nexisting type system, but delivers very significant benefits."]}),"\n",(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:"Type-Safe Input Polymorphism"}),": Offers a safe and scalable way to accept a\nvariety of inputs under a single structure—something previously hard to\nachieve in GraphQL."]}),"\n",(0,n.jsxs)(e.li,{children:[(0,n.jsx)(e.strong,{children:"Now part of the GraphQL standard"}),": Several GraphQL implementations\nincluding Ruby, Java, JavaScript and .NET already ship ",(0,n.jsx)(e.code,{children:"@oneOf"})," as a stable\nfeature"]}),"\n"]}),"\n",(0,n.jsxs)(e.p,{children:["You might wonder why this is expressed as a directive in SDL rather than\nexplicitly having a new type keyword; Brad Baker, contributor to GraphQL-Java,\nsummed it up in\n",(0,n.jsx)(e.a,{href:"https://github.com/graphql/graphql-spec/pull/825#issuecomment-1659900665",children:"this comment back in 2023"}),":"]}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsx)(e.p,{children:"use of the directive means that:"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsx)(e.li,{children:"it’s minimally invasive in terms of SDL tooling that might be out there,"}),"\n",(0,n.jsx)(e.li,{children:"it’s minimally invasive in terms of Introspection,"}),"\n",(0,n.jsx)(e.li,{children:"it’s minimally invasive in terms of engine implementation, it proved quite\neasy to implement in graphql-java."}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"Great stuff!"}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"Since then there have been a number of reports of success:"}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsxs)(e.p,{children:["I’m very happy with where this landed. We’d use it internally at my company. —\n",(0,n.jsx)(e.a,{href:"https://github.com/graphql/graphql-spec/pull/825#issuecomment-2128262620",children:"Ethan Resnick"})]}),"\n"]}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsxs)(e.p,{children:["More positive feedback: We are using it at HubSpot through the graphql-java\nimplementation and look forward to it becoming standardized. —\n",(0,n.jsx)(e.a,{href:"https://github.com/graphql/graphql-spec/pull/825#issuecomment-2128324080",children:"Henry Q. Dineen"})]}),"\n"]}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsxs)(e.p,{children:["I implemented support for OneOf input objects for the Caliban GraphQL library\n(Scala) […] it’s been fairly straightforward implementing support for it and\nI couldn’t really identify any areas that could have been improved. —\n",(0,n.jsx)(e.a,{href:"https://github.com/kyri-petrou",children:"kyri-petrou"})]}),"\n"]}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsxs)(e.p,{children:["We have been eagerly waiting at Jobber for this to land as well. […] We have\nmany use cases internally for it and we’re very excited to see this land! —\n",(0,n.jsx)(e.a,{href:"https://github.com/graphql/graphql-spec/pull/825#issuecomment-2135724148",children:"Clinton Pahl"})]}),"\n"]}),"\n",(0,n.jsxs)(e.blockquote,{children:["\n",(0,n.jsxs)(e.p,{children:["Colleagues at work (Atlassian) have been really happy with @oneOf, works\nexactly as you want it to and I haven’t heard any negative feedback. —\n",(0,n.jsx)(e.a,{href:"https://github.com/dondonz",children:"Donna Zhou"})]}),"\n"]}),"\n",(0,n.jsx)(e.h2,{id:s[3].id,children:s[3].value}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.code,{children:"@oneOf"})," is already available in at least the following implementations of GraphQL:"]}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsx)(e.li,{children:"GraphQL.js v16+"}),"\n",(0,n.jsx)(e.li,{children:"GraphQL Ruby v2.0.21+"}),"\n",(0,n.jsx)(e.li,{children:"GraphQL.NET v8+"}),"\n",(0,n.jsx)(e.li,{children:"GraphQL Java v21.2+"}),"\n",(0,n.jsx)(e.li,{children:"HotChocolate v16.0.0+"}),"\n",(0,n.jsx)(e.li,{children:"Strawberry GraphQL v0.230.0+"}),"\n",(0,n.jsx)(e.li,{children:"GraphQL Core (Python) v3.3.0+"}),"\n",(0,n.jsx)(e.li,{children:"webonyx/graphql-php (PHP) v15.21.0+"}),"\n",(0,n.jsx)(e.li,{children:"Probably others!"}),"\n"]}),"\n",(0,n.jsx)(e.h2,{id:s[4].id,children:s[4].value}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.code,{children:"@oneOf"})," allows for more expressive, capable, and less overwhelming schemas,\nhelping technical teams to move faster with increased safety. It’s simple and\neasy to implement, try it today!"]})]})},"/blog/2025-09-04-multioption-inputs-with-oneof",{filePath:"src/pages/blog/2025-09-04-multioption-inputs-with-oneof/index.mdx",timestamp:1789481543e3,pageMap:l.v,frontMatter:{title:"Safer Multi-option Inputs with `@oneOf`",tags:["announcements","spec"],date:"2025-09-04",byline:"Benjie Gillam",featured:!0},title:"Safer Multi-option Inputs with `@oneOf`"},"undefined"==typeof RemoteContent?r:RemoteContent.useTOC)}},function(i){i.O(0,[3556,5043,2888,9774,179],function(){return i(i.s=92148)}),_N_E=i.O()}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.