Docs Icon CaretRight How To Use GraphQL Icon CaretRight Schema & Type System

Schema & Type System

Unlike traditional REST APIs, GraphQL comes with a strong type system to describe your API. A GraphQL schema describes the data you can query using the API endpoint by defining a set of types and fields that are mapped to those types.

Read along to learn about various GraphQL types.

Object Types

Object types in GraphQL describe an object with underlying fields that can be queried from your API endpoint.

As an example, an object type can be defined as shown below:

1type actors {
2  name: String!
3  appearsIn: [movie!]!

Here,actors is an object type and name and appearsIn are fields mapped to type actors.

Scalar Types

From The GraphQL Documentation:

In the example for object types above, field name is of type String. String in GraphQL is by default a scalar type. This means that it resolves to a definite value and cannot have further sub-fields while querying. Scalar types represent the leaves of a query.

GraphQL comes with a set of default scalar types out-of-the-box such as below:

  • Int: A signed 32‐bit integer.
  • Float: A signed double-precision floating-point value.
  • String: A UTF‐8 character sequence.
  • Boolean: true or false.
  • ID: The ID scalar type represents a unique identifier, often used to re-fetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.

Fields can also be of types that are not scalar by default, but resolve to scalar values upon querying. For instance, in the following query, the name and appearsIn fields resolve to scalar types.

2  hero {
3    name
4    appearsIn
5  }

This is because in the schema, name and appearIn do not have further queryable sub-fields as described below:

2 "data": {
3   "hero": {
4     "name": "R2-D2",
5     "appearsIn": [
6       "NEWHOPE",
7       "EMPIRE",
8       "JEDI"
9     ]
10   }
11 }

Lists and Non-nulls

From the GraphQL documentation:

Object types, scalars, and enums are the only kinds of types you can define in GraphQL. But when you use the types in other parts of the schema, or in your query variable declarations, you can apply additional type modifiers that affect validation of those values.

Let's look at an example:

1type Character {
2  name: String!
3  appearsIn: [Episode]!

Here, we're using a String type and marking it as Non-Null by adding an exclamation mark ! after the type name. This means that our server always expects to return a non-null value for this field, and if it ends up getting a null value that will actually trigger a GraphQL execution error, letting the client know that something has gone wrong.

The Non-Null type modifier can also be used when defining arguments for a field, causing the GraphQL server to return a validation error if a null value is passed either in the GraphQL string or the variables.

1query DroidById($id: ID!) {
2 droid(id: $id) {
3   name
4 }
7 "id": null
2 "errors": [
3   {
4     "message": "Variable \"$id\" of non-null type \"ID!\" must not be null.",
5     "locations": [
6       {
7         "line": 1,
8         "column": 17
9       }
10     ]
11   }
12 ]
1myField: [String!]

This means that the list itself can be null, but it can't have any null members. For example, in JSON:

1myField: null // valid
2myField: [] // valid
3myField: ['a', 'b'] // valid
4myField: ['a', null, 'b'] // error

Union types

When a query returns a union type, you can use ... on to specify the query fields for a certain return type. These are also called inline fragments. For example, the hero query below returns a union type of either Droid or Human.

1query HeroForEpisode($ep: Episode!) {
2  hero(episode: $ep) {
3    name
4    ... on Droid {
5      primaryFunction
6    }
7    ... on Human {
8      height
9    }
10  }


Connections are a type of response used whenever you are expecting multiple results that may require pagination. Each query return type that ends in "Connection" will include the following return fields:

1pageInfo: PageInfo!
2edges: [SomethingEdge!]!
3nodes: [Something!]!


pageInfo returns an object that includes information about the returned page of results:

hasPreviousPage: Boolean! Whether or not the result has a previous page.

hasNextPage: Boolean! Whether or not the result has another page after it.

startCursor: String The starting cursor that identifies the first page.

endCursor: String The end cursor that identifies the last page.


edges returns an array of edge objects, which includes the cursor and first node for that page. You can use this data to help with pagination.


nodes returns an array of whichever type you are expecting paginated results for.


Each of these queries also accepts the following arguments: first: Int after: String last: Int before: String

first and last both accept an integer, which sets the number of results returned for each page. first will paginate the results starting at the beginning, while last will start from the end. It is required to pass an argument for either first or last. If no argument is given, the query will not return any results.

after and before both accept a cursor, which you can use to request different pages. These are both optional arguments.

You can learn more about the connection model and pagination in the official GraphQL docs here: Icon Link