NestJS Logo

Unions

Union types are similar to interfaces, but they don't specify any common fields between the types (see union types in the GraphQL documentation). Unions are useful for returning disjoint data types from a single field.

Code first#

To define a GraphQL union type, first define the classes that make up the union. Following the union type 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 ResultUnion union using the createUnionType function exported from the @nestjs/graphql package:


export const ResultUnion = createUnionType({
  name: 'ResultUnion',
  types: () => [Author, Book] as const,
});
Warning Add a const assertion (as const) to the array returned by the types property of the createUnionType function. Without it, TypeScript generates an incorrect declaration file at compile time, and using the union from another project fails with an error.

Now you can reference ResultUnion in a query:


@Query(() => [ResultUnion])
search(): Array<typeof ResultUnion> {
  return [new Author(), new Book()];
}

This generates 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 determines the type based on the value returned from the resolver method. This means that you must return class instances, not plain JavaScript object literals.

To provide a custom resolveType() function, pass the resolveType property in the options object of the createUnionType() function:


export const ResultUnion = createUnionType({
  name: 'ResultUnion',
  types: () => [Author, Book] as const,
  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, 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 GraphQL quick start chapter) to generate the 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 resolves to. Create a ResultUnionResolver class and define the __resolveType method, which returns the name of the concrete type. Remember to register ResultUnionResolver as a provider in a module.


@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.

Enums

Enumeration types are a special kind of scalar restricted to a particular set of allowed values (see enumeration types in the GraphQL documentation). They allow you to:

  • validate that any arguments of this type are one of the allowed values
  • communicate through the type system that a field will always be one of a finite set of values

Code first#

In the code first approach, you define a GraphQL enum type by creating a TypeScript enum:


export enum AllowedColor {
  RED,
  GREEN,
  BLUE,
}

With this in place, register the AllowedColor enum using the registerEnumType function exported from the @nestjs/graphql package:


registerEnumType(AllowedColor, {
  name: 'AllowedColor',
});

Now you can reference AllowedColor in your types:


@Field(type => AllowedColor)
favoriteColor: AllowedColor;

This generates the following part of the GraphQL schema in SDL:


enum AllowedColor {
  RED
  GREEN
  BLUE
}

To provide a description for the enum, pass the description property to the registerEnumType() function:


registerEnumType(AllowedColor, {
  name: 'AllowedColor',
  description: 'The supported colors.',
});

To provide descriptions for the enum values, or to mark a value as deprecated, pass the valuesMap property:


registerEnumType(AllowedColor, {
  name: 'AllowedColor',
  description: 'The supported colors.',
  valuesMap: {
    RED: {
      description: 'The default color.',
    },
    BLUE: {
      deprecationReason: 'Too blue.',
    },
  },
});

This generates the following GraphQL schema in SDL:


"""
The supported colors.
"""
enum AllowedColor {
  """
  The default color.
  """
  RED
  GREEN
  BLUE @deprecated(reason: "Too blue.")
}

Schema first#

To define an enum in the schema first approach, create a GraphQL enum with SDL:


enum AllowedColor {
  RED
  GREEN
  BLUE
}

Then you can use the typings generation feature (as shown in the GraphQL quick start chapter) to generate the corresponding TypeScript definitions:


export enum AllowedColor {
  RED = "RED",
  GREEN = "GREEN",
  BLUE = "BLUE"
}

Sometimes a backend uses a different internal value for an enum than the one exposed in the public API. In this example, the API contains RED, but resolvers use #f00 instead (see internal values in the Apollo documentation). To accomplish this, declare a resolver object for the AllowedColor enum:


export const allowedColorResolver: Partial<Record<keyof typeof AllowedColor, any>> = {
  RED: '#f00',
};
Hint All decorators are exported from the @nestjs/graphql package.

Then pass this resolver object in the resolvers property of the GraphQLModule#forRoot() method:


GraphQLModule.forRoot({
  resolvers: {
    AllowedColor: allowedColorResolver,
  },
});
Edit on GitHub

Support us

Nest is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you'd like to join them, please read more here.

Principal Sponsors

SerpApi LogoTrilon LogoMojam Logo

Sponsors / Partners

Become a sponsor