@@ -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,20 +22,20 @@ 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
38+ ``` js filename="ContentItemInterface.js"
3939import { GraphQLInterfaceType , GraphQLString , GraphQLNonNull } from ' graphql' ;
4040
4141const 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
7275import { GraphQLObjectType , GraphQLString , GraphQLNonNull } from ' graphql' ;
76+ import { ContentItemInterface } from ' ./ContentItemInterface.js' ;
7377
7478const ArticleType = new GraphQLObjectType ({
7579 name: ' Article' ,
@@ -105,11 +109,8 @@ GraphQL uses `resolveType`.
105109Use the ` GraphQLUnionType ` constructor to define a union. A union allows a field to return one
106110of 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
114115The 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
144146This function receives the following arguments:
145147
148+ { /* prettier-ignore */ }
146149``` js
147150resolveType (value, context, info)
148151```
149152
150153It 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 `
157160function. This fallback is less efficient and makes type resolution harder to debug. For most cases,
158161explicitly 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
165168For 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
186193GraphQL'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