Defining Union Types

Union types are defined with a list of object types:

const builder = new SchemaBuilder<{
Objects: {
GiraffeStringFact: { factKind: 'string'; fact: string };
GiraffeNumericFact: { factKind: 'number'; fact: string; value: number };
builder.objectType('GiraffeStringFact', {
fields: (t) => ({
fact: t.exposeString('fact', {}),
const GiraffeNumericFact = builder.objectType('GiraffeNumericFact', {
fields: (t) => ({
fact: t.exposeString('fact', {}),
value: t.exposeFloat('value', {}),
const GiraffeFact = builder.unionType('GiraffeFact', {
types: ['GiraffeStringFact', GiraffeNumericFact],
resolveType: (fact) => {
switch (fact.factKind) {
case 'number':
return GiraffeNumericFact;
case 'string':
return 'GiraffeStringFact';

The types array can either contain Object type names defined in TypeInfo, or and Object Ref created by object type. builder.objectType, builder.objectRef or other method, or a class that was used to implement an object type.

The resolveType function will be called with each item returned by a field that returns the unionType, and is used to determine which concrete the value corresponds to. It is usually good to have a shared property you can use to differentiate your union members.

Using Union Types

builder.queryField('giraffeFacts', (t) =>
type: [GiraffeFact],
resolve: () => {
const fact1 = {
factKind: 'string',
'A giraffe’s spots are much like human fingerprints. No two individual giraffes have exactly the same pattern',
} as const;
const fact2 = {
factKind: 'number',
fact: 'Top speed (MPH)',
value: 35,
} as const;
return [fact1, fact2];