Table of contents


  • What is GraphQL?
  • The Query
  • Introducing TypesIntroducing Object typesIntroducing scalar typesThe Query type
  • Scalars, Objects, and Lists
  • Nullability
  • Querying between Types
  • Schema
  • Enums
  • Interfaces & Unions
  • Arguments
  • Mutations

Try GraphOS  
The GraphQL developer platform

Introducing Types

"Is it THIS? Or is it THAT?"

To understand what something is, we often consider its characteristics: what makes it unique? What sets it apart from other things? What category could it belong to?

Types bring order into the growing world of data. Like big labeled boxes, they let us sift through the mess and logically sort "text" away from "numbers", and "timestamps" away from "unique identifiers."

Two boxes, labeled "numbers" and "text". Number type data is being sorted into the "numbers" box, while text data goes into the "text" box.

But grouping things into their types comes with more than just a label telling us what's inside. When we understand the type of data we're working with, we know what we can and can't do with it while programming: we can do certain things with numbers that we can't with text, for example! The data type we work with determines the kinds of operations and transformations we can perform on it.

GraphQL uses a type system to help us understand what kind of a thing a value is. A type system is a set of rules that defines the possible types of data that we can work with in a programming language. Working within these rules helps us organize our data and how we're using it, and it also makes it easier for us to represent relationships between different types, as we'll see in this article.

We define the specific types for the data we want to query and work with in a document called our GraphQL schema, which we'll explore in an upcoming section. But to get started, let's dig into the two main categories of types in GraphQL: object types and scalar types.

Introducing Object types

Object types represent something with properties, or fields, that we want to retrieve data for. Think of these as characteristics that we want to know about, or the details that make the object important for whatever we're building.

A fruit stall at a farmer's market could represent Fruit as an object type, and define fields such as name, quantity, price and hasEdibleSeeds.

A blueberry is specified as a Fruit type with fields for name, quantity, hasEdibleSeeds, averageWeight, and price.

With these fields, the Fruit type could represent a lot of different kinds of fruit beyond just blueberries. That's because the Fruit type by itself is non-specific: it doesn't automatically represent a particular kind of fruit, but rather serves as a broader category that many different kinds of fruit could fit into. The fields name, quantity, averageWeight, price, and hasEdibleSeeds can all be applied to fruit varieties and, in turn, hold different values.

To define an object type, we use the type keyword, followed by the name we'd like to use. Next, we open up a pair of curly braces; this is where we'll end up defining all of the fields that make up the Fruit type.

type Fruit {
# a Fruit object has a name, quantity, averageWeight, price, and hasEdibleSeeds

We can think of the Fruit type as a kind of structure: it defines the requirements that anything that calls itself "fruit" should follow. It's like a big label we can stick on anything that fits the qualifications; and it also gives us a clear idea of what's not included in the type.

A box labeled "Fruit" containing many fruits, alongside an onion labeled as "not fruit!"

But what about the actual type of data being provided for each field? How do we know that name returns a word like "blueberry", and that quantity returns some kind of number we can do calculations on? For this, we have a separate category of types: scalar types.

Introducing scalar types

Check out the Fruit type below. Inside of its curly braces, we'll find a name property.

type Fruit {
name: String

Right now, this is the only field the Fruit type has; it lets us know that name is a bit of data we can expect to find on objects categorized as Fruit.

You'll notice that it also defines something else: name returns a type called String.

String is one of several scalar types we can use to describe the kind of data a field returns. Scalar types represent primitive values—they don't contain fields, like object types do—and we use them to categorize values such as text, numbers, and true or false, along with a few others.

The available scalar types in GraphQL are String, Int, Float, Boolean and ID.

We can see a few of these in action by filling out the remaining fields on the Fruit type—and visualizing them applied to an actual fruit that Fruit could represent.

The Fruit type definition compared to an instance of that type.

Using this example, we can gather a few clues about what each scalar type is responsible for:

  • String represents words, letters, and characters
  • Int and Float are used to represent numeric values
  • Boolean represents the value true or the value false

In the next section, we'll explore each of the scalar types in greater detail, and learn how to put them to work for us in a query.

The Query type

In order to query a GraphQL service for any kind of data at all, it needs to define a special kind of object type called Query. This type defines how, and what, we can read from a service, and like the other types we've talked about, it lives in a GraphQL service's schema.

Query is considered a "root" type because it acts as the entry point to everything we're allowed to query for. Asking for data without it would be a lot like trying to enter a warehouse without a door. In the same way that a front door lets us into a building with hallways leading to different rooms, the Query type provides us with the possible query pathways we can use to get to data.

Implemented in GraphQL, the Query type looks like any other object type with a name and fields.

type Query {
mostPopularFruit: Fruit

The Query type's fields are what we use to send specific requests for data. In this example, Query has just one field, mostPopularFruit, which returns a Fruit object when queried. We'll see how to plug our types together to query for actual data in an upcoming section on Querying between Types.

Up Next: Scalars, Objects, and Lists  

About is maintained by the Apollo team. Our goal is to give developers and technical leaders the tools they need to understand and adopt GraphQL. 2024