@@ -5,7 +5,7 @@ title: Abstract types in GraphQL.js
55GraphQL includes two kinds of abstract types: interfaces and unions. These types let a single
66field 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
99constructing types in JavaScript using the GraphQL.js type system, not the schema definition
1010language (SDL).
1111
@@ -22,21 +22,25 @@ flexibility while preserving validation, introspection, and tool support.
2222GraphQL 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
3232To 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
3636The following example defines a ` ContentItem ` interface for a publishing platform:
3737
38- ``` js
39- const { GraphQLInterfaceType , GraphQLString , GraphQLNonNull } = require (' graphql' );
38+ ``` js filename="ContentItemInterface.js"
39+ const {
40+ GraphQLInterfaceType ,
41+ GraphQLString ,
42+ GraphQLNonNull ,
43+ } = require (' graphql' );
4044
4145const ContentItemInterface = new GraphQLInterfaceType ({
4246 name: ' ContentItem' ,
@@ -55,10 +59,13 @@ const ContentItemInterface = new GraphQLInterfaceType({
5559 return null ;
5660 },
5761});
62+
63+ exports .ContentItemInterface = ContentItemInterface;
5864```
5965
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.
66+ The ` resolveType ` function must return either the string type name corresponding
67+ to the ` GraphQLObjectType ` of the given ` value ` , or ` null ` if the type could not
68+ be determined.
6269
6370## Implementing interfaces with object types
6471
@@ -70,6 +77,7 @@ conform to the `ContentItem` interface:
7077
7178``` js
7279const { GraphQLObjectType , GraphQLString , GraphQLNonNull } = require (' graphql' );
80+ const { ContentItemInterface } = require (' ./ContentItemInterface.js' );
7381
7482const ArticleType = new GraphQLObjectType ({
7583 name: ' Article' ,
@@ -105,11 +113,8 @@ GraphQL uses `resolveType`.
105113Use the ` GraphQLUnionType ` constructor to define a union. A union allows a field to return one
106114of several object types that don't need to share fields.
107115
108- A union requires:
109-
110- - A ` name `
111- - A list of object types (` types ` )
112- - A ` resolveType ` function
116+ A union requires a name and a list of object types (` types ` ). It should also be
117+ provided a ` resolveType ` function the same as explained for interfaces above.
113118
114119The following example defines a ` SearchResult ` union:
115120
@@ -134,39 +139,42 @@ const SearchResultType = new GraphQLUnionType({
134139});
135140```
136141
137- Unlike interfaces, unions don’t declare any fields of their own. Clients use inline fragments
138- to query fields from the concrete types .
142+ Unlike interfaces, unions don’t declare any fields their members must implement.
143+ Clients use a fragment with a type condition to query fields from a concrete type .
139144
140145## Resolving abstract types at runtime
141146
142- GraphQL resolves abstract types dynamically during execution using the ` resolveType ` function.
147+ GraphQL resolves abstract types dynamically during execution using the ` resolveType ` function, if
148+ present.
143149
144150This function receives the following arguments:
145151
152+ <!-- prettier-ignore -->
146153```js
147154resolveType(value, context, info)
148155```
149156
150157It can return:
151158
152- - A ` GraphQLObjectType ` instance (recommended)
153159- The name of a type as a string
160+ - `null` if the type could not be determined
154161- A `Promise` resolving to either of the above
155162
156- If ` resolveType ` isn't defined, GraphQL falls back to checking each possible type's ` isTypeOf `
163+ If `resolveType` isn't defined, GraphQL falls back to checking each possible type's `isTypeOf`
157164function. This fallback is less efficient and makes type resolution harder to debug. For most cases,
158165explicitly defining `resolveType` is recommended.
159166
160167## Querying abstract types
161168
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.
169+ To query a field that returns an abstract type, use fragments to select fields from the possible
170+ concrete types. GraphQL evaluates each fragment based on the runtime type of the result.
164171
165172For example:
166173
167174```graphql
168- {
169- search (term : " deep learning" ) {
175+ query Search($term: String! = " deep learning" ) {
176+ search (term : $term ) {
177+ # Inline fragments with type condition:
170178 ... on Book {
171179 title
172180 isbn
@@ -175,30 +183,34 @@ For example:
175183 name
176184 bio
177185 }
178- ... on Publisher {
179- name
180- catalogSize
181- }
186+ # Named fragment :
187+ ... publisherFrag
182188 }
183189}
190+
191+ fragment publisherFrag on Publisher {
192+ name
193+ catalogSize
194+ }
184195```
185196
186197GraphQL'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.
198+ enables code generation and editor tooling to provide type-aware completions; however you should
199+ keep in mind the possibility that more types will implement the interface or be included in the
200+ union in future, and thus ensure that you have a default case to handle additional types.
188201
189202## Best practices
190203
191204- 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.
193205- 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.
206+ types.
207+ - Test `resolveType` logic carefully. Errors in `resolveType` can cause runtime errors that can
208+ be hard to trace.
197209- Use interfaces when types share fields and unions when types are structurally unrelated.
198210
199211## Additional resources
200212
201213- [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 )
214+ - GraphQL Specification:
215+ - [Interfaces](https://spec.graphql.org/October2021/#sec-Interfaces)
216+ - [Unions](https://spec.graphql.org/October2021/#sec-Unions)
0 commit comments