Join us on Nov 7 for GraphQL Summit Virtual
Join API innovators, GraphQL experts, and AI trailblazers on Nov 7 at GraphQL Summit Virtual. Register for free →
GraphQL types are great for consistency (we know what data to expect from a particular type) and efficiency (types can reference other types, which we'll see soon). To maximize their power, the types that we create and maintain should reflect what's needed from our data and how it's being used.
In this section, we'll dive deeper into three fundamental types that let us define our data and express relationships: scalar types, object types, and the List
type.
We'll refer to the following Fruit
type as we explore each of the scalar types.
type Fruit {name: Stringquantity: Intprice: IntaverageWeight: FloathasEdibleSeeds: Boolean}
If we ask for the fruit's name
, we expect a specific word or label that will help us identify the particular fruit we're looking at. In GraphQL, we represent this kind of data—characters and text, either in single words or strung together in sentences—using the scalar type String
.
When a field is "typed" as a String
, the text it hands back as its value should be written with Unicode characters contained in quotation marks. Here, we can understand "characters" as the units of human writing systems (like the letters of the Latin alphabet, which English uses).
There are three fields on the Fruit
type that return number values, but altogether we're actually representing two different kinds of data. Let's start by taking a look at the quantity
and price
fields.
The quantity
field, which keeps track of how many of an item are in stock, shouldn't be a fraction (we won't sell half a blueberry, or maintain a stock of 13.33 pears). For this reason, valid values of the quantity
field should be represented by the scalar type Int
.
The Int
type, short for "integer", is ideal for this use case as it's used to represent 32-bit numbers: positive or negative non-fractional numbers, including zero, that can be written in binary using up to 32 digits of 1s and 0s.
So if the Int
type is used to represent non-fractional numbers, why would we use it to represent the type of data we expect the price
field to provide? After all, we would probably expect an item's price to look something like this: 2.99
.
Well, it's actually not the wisest practice to use fractional numbers, or decimals, when storing currency data. Most modern systems will represent monetary amounts like an item's cost in terms of the currency's smallest indivisible component—such as a penny! This lets us represent prices in a form that won't result in lost data as more and more computations are done on the number. In this case, instead of 2.99
, the equivalent amount in pennies would be 299
!
Check out the important note in the following section on the Float
type to learn more.
In contrast to quantity
and price
, the averageWeight
field on the Fruit
type is an actual decimal—or floating point—number! Numbers represented by the Float
type allow for more granular fluctuations in value as they increase or decrease. The weight of a pear in kilograms—0.18
, on average—differs considerably from the weight of a single blueberry at 0.0005
kilograms! Without this ability to represent fractional numbers, we couldn't visualize these very precise differences. We'd either need to truncate both items' averageWeight
to 0
kilograms, or inflate them both to 1
! Not terrifically accurate. To represent numbers of this type, we'll use the scalar type Float
.
The last field (hasEdibleSeeds
) on the Fruit
type should provide something like a "yes" or "no" answer to whether a particular fruit type contains edible seeds. We've given this field a Boolean
type, which tells us that we can expect a true
or false
value when we query a fruit type's hasEdibleSeeds
field. There is no halfway point between true
and false
—no "maybe" or "almost"—so we can think of Boolean
fields like light switches, because we toggle them between two discrete values much like "on" and "off".
GraphQL provides another scalar type out of the box that we haven't yet used here. It's the ID
type, and like any ID (such as your driver's license or passport), its purpose is to help us identify something unique. When an object type includes a field with type ID
, we can use it to definitively specify which object we're talking about, particularly if other fields—even the seemingly unique name
field on our Fruit
type—have the potential to be the same!
We can supplement our Fruit
type with an ID simply by defining a new field and setting it as type ID
. A standard name for this field is id
, because many frameworks working with GraphQL know how to handle it by default.
type Fruit {id: IDname: Stringquantity: Intprice: IntaverageWeight: FloathasEdibleSeeds: Boolean}
The Apollo Sandbox below includes an operation that currently requests the name
and quantity
fields for mostPopularFruit
. Use the left-hand panel titled "Documentation" to explore the Fruit
type. YOu can also use it to test out adding other fields, then run the query to see what data appears in the Response panel.
The Documentation panel in Apollo Sandbox lets you explore all of the types of fields in a GraphQL service's schema. You can collapse or reopen it by toggling the two arrows at the top of the panel.
As you can see from the fields we've discussed on the Fruit
type, we expect fields denoted with a scalar type to hand back a single, self-contained value such as a name, a line of text in quotations, a number, or a true/false value.
This works well in a lot of cases: sometimes we only need a single piece of data for each field. But GraphQL also gives us a way to represent that a field should have the ability to return more than one item. We can achieve this using the List type.
The List type is considered a "wrapping type" in GraphQL, because unlike the scalar types we've seen so far, we don't use a particular label or keyword to denote a field as a list; instead, we use square brackets ([]
) to enclose the name of the data type the list contains.
nutrients: [String]
This means that a field can return more than one item—but it doesn't have to! A list might contain just one item, or even no items at all. But when an object has multiple bits of data that relate to just one of its fields, lists can be particularly useful.
Let's add the nutrients
field we saw above to the Fruit
type. This new field allows us to express more than the single most prevalent vitamin or mineral that the fruit contains. We might use it to provide information about the three most concentrated nutrients in a fruit, and let this drive customers' purchasing decisions.
type Fruit {id: IDname: Stringquantity: Intprice: IntaverageWeight: FloathasEdibleSeeds: Booleannutrients: [String]}
Try it out! Click into mostPopularFruit
from the Documentation panel, then add the nutrients
field to the query below.
About
GraphQL.com is maintained by the Apollo team. Our goal is to give developers and technical leaders the tools they need to understand and adopt GraphQL.
GraphQL.com 2024