Unions
Union types are very similar to interfaces, but they don’t get to specify any common fields between the types (read more here). Unions are useful for returning disjoint data types from a single field.
Code first
To define a GraphQL union type, we must define classes that this union will be composed of. Following the example from the Apollo documentation, we’ll create two classes. First, Book
:
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Book {
@Field()
title: string;
}
And then Author
:
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Author {
@Field()
name: string;
}
With this in place, register the Result
union using the createUnionType
function exported from the @nestjs/graphql
package:
export const ResultUnion = createUnionType({
name: 'Result',
types: () => [Author, Book],
});
Now, we can reference the ResultUnion
in our query:
@Query(returns => [ResultUnion])
search(): Array<typeof ResultUnion> {
return [new Author(), new Book()];
}
This will result in generating the following part of the GraphQL schema in SDL:
type Author {
name: String!
}
type Book {
title: String!
}
union ResultUnion = Author | Book
type Query {
search: [ResultUnion!]!
}
The default resolveType()
function generated by the library will extract the type based on the value returned from the resolver method. That means returning class instances instead of literal JavaScript object is obligatory.
To provide a customized resolveType()
function, pass the resolveType
property to the options object passed into the createUnionType()
function, as follows:
export const ResultUnion = createUnionType({
name: 'Result',
types: () => [Author, Book],
resolveType(value) {
if (value.name) {
return Author;
}
if (value.title) {
return Book;
}
return null;
},
});
Schema first
To define a union in the schema first approach, simply create a GraphQL union with SDL.
type Author {
name: String!
}
type Book {
title: String!
}
union ResultUnion = Author | Book
Then, you can use the typings generation feature (as shown in the quick start chapter) to generate corresponding TypeScript definitions:
export class Author {
name: string;
}
export class Book {
title: string;
}
export type ResultUnion = Author | Book;
Unions require an extra __resolveType
field in the resolver map to determine which type the union should resolve to. Let’s create a ResultUnionResolver
class and define the __resolveType
method:
@Resolver('ResultUnion')
export class ResultUnionResolver {
@ResolveField()
__resolveType(value) {
if (value.name) {
return 'Author';
}
if (value.title) {
return 'Book';
}
return null;
}
}
Hint All decorators are exported from the
@nestjs/graphql
package.