Pothos GraphQL
Searching...

Enums

Defining Enum Types

Enums can be defined a number of different ways:

  1. Using typescript enums

    export enum Diet {
      HERBIVOROUS,
      CARNIVOROUS,
      OMNIVORIOUS,
    }
    
    builder.enumType(Diet, {
      name: 'Diet',
    });
    
  2. Using an array of strings

    export const LengthUnit = builder.enumType('LengthUnit', {
      values: ['Feet', 'Meters'] as const,
    });
    

    Note that we use as const to allow ts to properly type our enum values.

  3. Using a values object:

    export const GiraffeSpecies = builder.enumType('GiraffeSpecies', {
      values: {
        Southern: {
          description: 'Also known as two-horned giraffe',
          value: 'giraffa',
        },
        Masai: {
          value: 'tippelskirchi',
        },
        Reticulated: {
          value: 'reticulata',
        },
        Northern: {
          value: 'camelopardalis',
        },
      } as const,
    });
    

    Again we use as const here to allow the enum values to be correctly inferred. The as const can also be added to the values instead, or omitted if the values are already defined using a variable that typescript can type correctly.

    Using a values object like this enables defining additional options like a description for each enum value.

    Using a values object also allows the name of the enum value to be different from the typescript value used internally in your resolvers.

    The keys (eg Southern) are used as the name of the enum value in you GraphQL schema, and the value (eg. 'giraffa') property is used as the value you will receive in the arguments for your resolvers, or the value you need to return from your resolvers. This is similar to how typescript enum values can be assigned string or numeric values.

  4. Using an object with as const

    const VehicleType = {
      sedan: 'SEDAN',
      suv: 'SUV',
      truck: 'TRUCK',
      motorcycle: 'MOTORCYCLE',
    } as const;
    
    const VehicleTypeEnum = builder.enumType('VehicleType', {
      values: Object.fromEntries(
        Object.entries(VehicleType).map(([name, value]) => [name, { value }]),
      ),
    });
    

    Modern TypeScript may prefer using objects with as const over enums to align with JavaScript standards. This approach essentially mirrors the "array of strings" method. You can use Object.toEntries and Object.fromEntries to turn convert to Object values form described above.

    For more detailed information, you can refer to the TypeScript handbook on Objects vs Enums.

    Alternatively, using Object.keys or Object.values will allow you to produce an enum that uses just the keys or values of the object for both the internal typescript and name in the GraphQL schema.

    const VehicleType = {
      sedan: 'SEDAN',
      suv: 'SUV',
      truck: 'TRUCK',
      motorcycle: 'MOTORCYCLE',
    } as const;
    
    const VehicleTypeEnum = builder.enumType('VehicleType', {
      values: Object.values(VehicleType),
    });
    // Or
    const VehicleTypeEnum = builder.enumType('VehicleType', {
      values: Object.keys(VehicleType) as (keyof typeof VehicleType)[],
    });
    

Using Enum Types

Enums can be referenced either by the Ref that was returned by calling builder.enumType or by using the typescript enum. They can be used either as arguments, or as field return types:

builder.objectFields('Giraffe', (t) => ({
  height: t.float({
    args: {
      unit: t.arg({
        type: LengthUnit,
        required: true,
        defaultValue: 'Meters',
      }),
    },
    resolve: (parent, args) =>
      args.unit === 'Meters' ? parent.heightInMeters : parent.heightInMeters * 3.281,
  }),
  diet: t.field({
    description:
      'While Giraffes are herbivores, they do eat the bones of dead animals to get extra calcium',
    type: Diet,
    resolve: () => Diet.HERBIVOROUS,
  }),
  species: t.field({
    type: GiraffeSpecies,
    resolve: () => 'camelopardalis' as const,
  }),
}));