We will continue with the same repository as in the previous article on GraphQL scalars. You can clone the GitHub repository using this command
install dependencies with
and start the server in development with
You should be now able to access GraphQL Playground
In this part, we will go through the fields that use Enum fields in our previously defined schema. If you are new to GraphQL, it might also be helpful to check out our previous articles on built-in scalars as well as the one on input object type. We use them as prerequisites for this article in terms of understanding GraphQL, and we will also use parts of the code that we built in previous articles. In the following image we illustrate the hierarchical tree graph of the response for our queries and mutations
Enums are basically a special type we can use to enumerate all possible values in the field. By using Enums we are adding another kind of validation to existing GraphQL schema. The specified values of the Enum type are the only possible options that are accepted. Now let’s go right into the implementation. Let’s consider that in our Task type we also define Enum for the task state. We design this enum type with the consideration that a given task can have one of three states:
In the GraphQL query language we can write it in the following form
It is common good practice to label enum values as capitalized values. In GraphQL language, these values are automatically mapped to the name of the value. However, when we rewrite the TaskStateEnum with graphql-js, we can also write the enum type in the following form:
The enum class allows us to map enum values to internal values represented by integers (or different strings etc.). By defining enumerated values to an integer leads you to design your schema in the most efficient way in terms of performance. In our case, we did not use any real database and did not send it to some more complex backend infrastructure. However, in production you will often use some monolithic or microservice architecture. It is much more efficient to send these enum values using integers, as the size is much smaller and can be transferred over the network more quickly. Also, it is more efficient to store integer values in the database.
Including our Enum in the database
Now we can implement our defined state in our Task definition:
We will also use our TaskStateEnumType for validating input when creating task. The type called CreateTaskInput is defined as follows:
You can also see, that we defined defaultValue for state field with in-build function called getValue, which is available for all Enum objects. It is a good practice to define all enumerated fields at one place and then just reuse them through the whole codebase.
All possible values for the state field are now available through introspection and can be viewed in GraphQL Playground in the Docs tab. The Schema can be also written in SDL:
Now let’s move on to result and input coercion for enums. If you do not know what that means, it might be useful to go through the article on scalars and its input and result coercion, where we explain these terms.
Result coercion for enums
If we receive a different value from the database, that is not defined in the enum type, an error is raised. For example, let’s change the value of the model Task state in the “in-memory” db (task-db.ts) to badstate.
And then execute the following query for retrieving tasks from the server:
The GraphQL server will raise the following error:
The important thing to recognize is also the fact that if we change the state from integer value 1 (UNASSIGNED) to the string value UNASSIGNED the GraphQL will also raises the same type of error:
GraphQL server takes care about internal value mapping when dealing with result coercion, therefore will raise the error when no internal enum values matches the received data. If the data are matched to enumerated values, these data values are then mapped according to enum specification, e.g. 2 will be mapped to IN_PROGRESS. However, when we use float 1.0 as a value for the state field of the task in the “in-memory” DB. The value is then transformed to the integer 1 and GraphQL does not raise an error as the data are available in the TaskStateEnum specification.
Input coercion for enums
When we deal with input coercion for enums, we have to take into account additional validation for enumerated values. The GraphQL server will check if the values for the enum field matches defined values in the schema. Therefore if we execute the following mutation for adding task with state argument badstate
the GraphQL server would raise the following error.
The common error when using Enums is the execution of this createTask mutation
It is not always expected that we will get the following error
The correct way to pass enum inline arguments in GraphQL Playground is just to specify enumerated values without the quotation
This is different, of course, when we specify mutations using variables, as the variable has to be written according to JSON syntax specification. When using variables the GraphQL document will look as follows:
with this variables:
In GraphQL, Enum type can be used as input and output type. Enums are the great way to add additional validation constraints. We can list the values with introspection query:
and reuse the Enumerated types across our whole code base.