Enums (short for Enumerations) in GraphQL are a special kind of scalar that is restricted to a particular set of allowed values. They are useful for representing a fixed set of options, such as the days of the week, user roles, or status codes.
Key Concepts
- Definition: Enums are defined in the GraphQL schema using the
enum
keyword. - Usage: Enums can be used as the type for fields, arguments, and input types.
- Validation: GraphQL ensures that only the defined values are used, providing a layer of validation.
Defining Enums
Enums are defined in the schema with the enum
keyword followed by the name of the enum and the set of allowed values.
In this example, Role
is an enum with three possible values: ADMIN
, USER
, and GUEST
.
Using Enums in Schemas
Enums can be used in various parts of the schema, such as in object types, input types, and arguments.
Example: Using Enums in Object Types
Here, the role
field in the User
type is of type Role
, meaning it can only have one of the values defined in the Role
enum.
Example: Using Enums in Input Types
input CreateUserInput { name: String! role: Role! } type Mutation { createUser(input: CreateUserInput!): User }
In this example, the CreateUserInput
input type uses the Role
enum for the role
field. This ensures that when creating a user, the role must be one of the allowed values.
Practical Example
Let's create a simple GraphQL schema that includes an enum for user roles and a mutation to create a user.
Schema Definition
enum Role { ADMIN USER GUEST } type User { id: ID! name: String! role: Role! } input CreateUserInput { name: String! role: Role! } type Mutation { createUser(input: CreateUserInput!): User } type Query { users: [User] }
Resolver Implementation
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` enum Role { ADMIN USER GUEST } type User { id: ID! name: String! role: Role! } input CreateUserInput { name: String! role: Role! } type Mutation { createUser(input: CreateUserInput!): User } type Query { users: [User] } `; let users = []; let idCounter = 1; const resolvers = { Query: { users: () => users, }, Mutation: { createUser: (_, { input }) => { const user = { id: idCounter++, ...input }; users.push(user); return user; }, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Explanation
- Schema Definition: We define an enum
Role
with three values:ADMIN
,USER
, andGUEST
. TheUser
type has arole
field of typeRole
. TheCreateUserInput
input type also uses theRole
enum for therole
field. - Resolvers: We implement a simple resolver for the
createUser
mutation that adds a new user to theusers
array. Therole
field is validated against theRole
enum.
Exercises
Exercise 1: Add a New Enum
- Define a new enum
Status
with valuesACTIVE
,INACTIVE
, andBANNED
. - Add a
status
field to theUser
type using theStatus
enum. - Update the
CreateUserInput
input type to include thestatus
field.
Solution
enum Status { ACTIVE INACTIVE BANNED } type User { id: ID! name: String! role: Role! status: Status! } input CreateUserInput { name: String! role: Role! status: Status! } type Mutation { createUser(input: CreateUserInput!): User } type Query { users: [User] }
Exercise 2: Implement the Resolver
- Update the resolver for the
createUser
mutation to handle the newstatus
field.
Solution
const resolvers = { Query: { users: () => users, }, Mutation: { createUser: (_, { input }) => { const user = { id: idCounter++, ...input }; users.push(user); return user; }, }, };
Common Mistakes
- Using Undefined Enum Values: Ensure that only the values defined in the enum are used. GraphQL will throw an error if an undefined value is used.
- Case Sensitivity: Enum values are case-sensitive.
ADMIN
andadmin
are considered different values.
Conclusion
Enums in GraphQL provide a way to define a set of allowed values for a field, ensuring data consistency and validation. They are easy to define and use in your schema, making them a powerful tool for creating robust APIs. In the next module, we will explore more advanced schema design concepts, such as interfaces and unions.