Skip to content

Commit cdd586e

Browse files
JoviDeCroockbenjie
authored andcommitted
Write about @oneOf in the graphql-js documentation (#4290)
Currently input-unions and by extension the `@oneOf` directive aren't present in the documentation. I have opted to put this into the advanced section. The copy might be up for improvement, honestly fire away if there's more cases to cover, just wanted to get the ball rolling here. CC @benjie --------- Co-authored-by: Benjie <[email protected]>
1 parent 50197a3 commit cdd586e

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

cspell.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ words:
113113
- tailwindcss
114114
- svgr
115115
- ruru
116+
- oneof
116117

117118
# used as href anchors
118119
- graphqlerror

website/pages/_meta.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const meta = {
1717
title: 'Advanced Guides',
1818
},
1919
'constructing-types': '',
20+
'oneof-input-objects': 'OneOf input objects',
2021
'defer-stream': '',
2122
'-- 3': {
2223
type: 'separator',

website/pages/oneof-input-objects.mdx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: OneOf input objects
3+
---
4+
5+
import { Tabs } from 'nextra/components';
6+
7+
Some inputs will behave differently depending on what input we choose. Let's look at the case for
8+
a field named `product`, we can fetch a `Product` by either its `id` or its `name`. Currently we'd
9+
make a tradeoff for this by introducing two arguments that are both nullable, now if both are passed
10+
as null (or both non-null) we'd have to handle that in code - the type system wouldn't indicate that exactly one was required. To fix this, the `@oneOf` directive was introduced so we
11+
can create this "exactly one option" constraint without sacrificing the strictly typed nature of our GraphQL Schema.
12+
13+
<Tabs items={['SDL', 'Code']}>
14+
<Tabs.Tab>
15+
```js
16+
const schema = buildSchema(`
17+
type Product {
18+
id: ID!
19+
name: String!
20+
}
21+
22+
input ProductLocation {
23+
aisleNumber: Int!
24+
shelfNumber: Int!
25+
positionOnShelf: Int!
26+
}
27+
28+
input ProductSpecifier @oneOf {
29+
id: ID
30+
name: String
31+
location: ProductLocation
32+
}
33+
34+
type Query {
35+
product(by: ProductSpecifier!): Product
36+
}
37+
`);
38+
```
39+
</Tabs.Tab>
40+
<Tabs.Tab>
41+
```js
42+
const Product = new GraphQLObjectType({
43+
name: 'Product',
44+
fields: {
45+
id: {
46+
type: new GraphQLNonNull(GraphQLID),
47+
},
48+
name: {
49+
type: new GraphQLNonNull(GraphQLString),
50+
},
51+
},
52+
});
53+
54+
const ProductLocation = new GraphQLInputObjectType({
55+
name: 'ProductLocation',
56+
isOneOf: true,
57+
fields: {
58+
aisleNumber: { type: GraphQLInt },
59+
shelfNumber: { type: GraphQLInt },
60+
positionOnShelf: { type: GraphQLInt },
61+
},
62+
});
63+
64+
const ProductSpecifier = new GraphQLInputObjectType({
65+
name: 'ProductSpecifier',
66+
isOneOf: true,
67+
fields: {
68+
id: { type: GraphQLID },
69+
name: { type: GraphQLString },
70+
location: { type: ProductLocation },
71+
},
72+
});
73+
74+
const schema = new GraphQLSchema({
75+
query: new GraphQLObjectType({
76+
name: 'Query',
77+
fields: {
78+
product: {
79+
type: Product,
80+
args: { by: { type: ProductSpecifier } },
81+
},
82+
},
83+
}),
84+
});
85+
```
86+
</Tabs.Tab>
87+
</Tabs>
88+
89+
It doesn't matter whether you have 2 or more inputs here, all that matters is
90+
that your user will have to specify one, and only one, for this input to be valid.
91+
The values are not limited to scalars, lists and other input object types are also allowed.

0 commit comments

Comments
 (0)