Skip to content

Commit eb858bc

Browse files
authored
docs: editorial on abstract types page (#4394)
Editorial on #4393
1 parent 90aaadc commit eb858bc

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

website/pages/docs/abstract-types.mdx

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ title: Abstract types in GraphQL.js
55
GraphQL includes two kinds of abstract types: interfaces and unions. These types let a single
66
field return values of different object types, while keeping your schema type-safe.
77

8-
This guide covers how to define and resolve abstract types using GraphQL.js. It focuses on
8+
This guide covers how to define and resolve abstract types using GraphQL.js. It focuses on
99
constructing types in JavaScript using the GraphQL.js type system, not the schema definition
1010
language (SDL).
1111

@@ -22,20 +22,20 @@ flexibility while preserving validation, introspection, and tool support.
2222
GraphQL provides two kinds of abstract types:
2323

2424
- Interfaces define a set of fields that multiple object types must implement.
25-
- Use case: A `ContentItem` interface with fields like `id`, `title`, and `publishedAt`,
25+
- Use case: A `ContentItem` interface with fields like `id`, `title`, and `publishedAt`,
2626
implemented by types such as `Article` and `PodcastEpisode`.
2727
- Unions group together unrelated types that don't share any fields.
28-
- Use case: A `SearchResult` union that includes `Book`, `Author`, and `Publisher` types.
28+
- Use case: A `SearchResult` union that includes `Book`, `Author`, and `Publisher` types.
2929

3030
## Defining interfaces
3131

3232
To define an interface in GraphQL.js, use the `GraphQLInterfaceType` constructor. An interface
33-
must include a `name`, a `fields` function, and a `resolveType` function, which tells GraphQL which
34-
concrete type a given value corresponds to.
33+
must include a `name`, definition of the shared `fields`, and should include a `resolveType`
34+
function telling GraphQL which concrete type a given value corresponds to.
3535

3636
The following example defines a `ContentItem` interface for a publishing platform:
3737

38-
```js
38+
```js filename="ContentItemInterface.js"
3939
import { GraphQLInterfaceType, GraphQLString, GraphQLNonNull } from 'graphql';
4040

4141
const ContentItemInterface = new GraphQLInterfaceType({
@@ -55,10 +55,13 @@ const ContentItemInterface = new GraphQLInterfaceType({
5555
return null;
5656
},
5757
});
58+
59+
exports.ContentItemInterface = ContentItemInterface;
5860
```
5961

60-
You can return either the type name as a string or the corresponding `GraphQLObjectType` instance.
61-
Returning the instance is recommended when possible for better type safety and tooling support.
62+
The `resolveType` function must return either the string type name corresponding
63+
to the `GraphQLObjectType` of the given `value`, or `null` if the type could not
64+
be determined.
6265

6366
## Implementing interfaces with object types
6467

@@ -70,6 +73,7 @@ conform to the `ContentItem` interface:
7073

7174
```js
7275
import { GraphQLObjectType, GraphQLString, GraphQLNonNull } from 'graphql';
76+
import { ContentItemInterface } from './ContentItemInterface.js';
7377

7478
const ArticleType = new GraphQLObjectType({
7579
name: 'Article',
@@ -105,11 +109,8 @@ GraphQL uses `resolveType`.
105109
Use the `GraphQLUnionType` constructor to define a union. A union allows a field to return one
106110
of several object types that don't need to share fields.
107111

108-
A union requires:
109-
110-
- A `name`
111-
- A list of object types (`types`)
112-
- A `resolveType` function
112+
A union requires a name and a list of object types (`types`). It should also be
113+
provided a `resolveType` function the same as explained for interfaces above.
113114

114115
The following example defines a `SearchResult` union:
115116

@@ -134,39 +135,42 @@ const SearchResultType = new GraphQLUnionType({
134135
});
135136
```
136137

137-
Unlike interfaces, unions don't declare any fields of their own. Clients use inline fragments
138-
to query fields from the concrete types.
138+
Unlike interfaces, unions don't declare any fields their members must implement.
139+
Clients use a fragment with a type condition to query fields from a concrete type.
139140

140141
## Resolving abstract types at runtime
141142

142-
GraphQL resolves abstract types dynamically during execution using the `resolveType` function.
143+
GraphQL resolves abstract types dynamically during execution using the `resolveType` function, if
144+
present.
143145

144146
This function receives the following arguments:
145147

148+
{/* prettier-ignore */}
146149
```js
147150
resolveType(value, context, info)
148151
```
149152

150153
It can return:
151154

152-
- A `GraphQLObjectType` instance (recommended)
153155
- The name of a type as a string
156+
- `null` if the type could not be determined
154157
- A `Promise` resolving to either of the above
155158

156-
If `resolveType` isn't defined, GraphQL falls back to checking each possible type's `isTypeOf`
159+
If `resolveType` isn't defined, GraphQL falls back to checking each possible type's `isTypeOf`
157160
function. This fallback is less efficient and makes type resolution harder to debug. For most cases,
158161
explicitly defining `resolveType` is recommended.
159162

160163
## Querying abstract types
161164

162-
To query a field that returns an abstract type, use inline fragments to select fields from the
163-
possible concrete types. GraphQL evaluates each fragment based on the runtime type of the result.
165+
To query a field that returns an abstract type, use fragments to select fields from the possible
166+
concrete types. GraphQL evaluates each fragment based on the runtime type of the result.
164167

165168
For example:
166169

167170
```graphql
168-
{
169-
search(term: "deep learning") {
171+
query Search($term: String! = "deep learning") {
172+
search(term: $term) {
173+
# Inline fragments with type condition:
170174
... on Book {
171175
title
172176
isbn
@@ -175,30 +179,34 @@ For example:
175179
name
176180
bio
177181
}
178-
... on Publisher {
179-
name
180-
catalogSize
181-
}
182+
# Named fragment:
183+
...publisherFrag
182184
}
183185
}
186+
187+
fragment publisherFrag on Publisher {
188+
name
189+
catalogSize
190+
}
184191
```
185192

186193
GraphQL's introspection system lists all possible types for each interface and union, which
187-
enables code generation and editor tooling to provide type-aware completions.
194+
enables code generation and editor tooling to provide type-aware completions; however you should
195+
keep in mind the possibility that more types will implement the interface or be included in the
196+
union in future, and thus ensure that you have a default case to handle additional types.
188197

189198
## Best practices
190199

191200
- Always implement `resolveType` for interfaces and unions to handle runtime type resolution.
192-
- Return the `GraphQLObjectType` instance when possible for better clarity and static analysis.
193201
- Keep `resolveType` logic simple, using consistent field shapes or tags to distinguish
194-
types.
195-
- Test `resolveType` logic carefully. Errors in `resolveType` can cause runtime errors that can
196-
be hard to trace.
202+
types.
203+
- Test `resolveType` logic carefully. Errors in `resolveType` can cause runtime errors that can
204+
be hard to trace.
197205
- Use interfaces when types share fields and unions when types are structurally unrelated.
198206

199207
## Additional resources
200208

201209
- [Constructing Types](https://www.graphql-js.org/docs/constructing-types/)
202-
- GraphQL Specification:
203-
- [Interfaces](https://spec.graphql.org/October2021/#sec-Interfaces)
204-
- [Unions](https://spec.graphql.org/October2021/#sec-Unions)
210+
- GraphQL Specification:
211+
- [Interfaces](https://spec.graphql.org/October2021/#sec-Interfaces)
212+
- [Unions](https://spec.graphql.org/October2021/#sec-Unions)

0 commit comments

Comments
 (0)