GraphQL Type Language, commonly known as Schema Definition Language (SDL), provides a language-independent syntax for defining a GraphQL API's schema. It describes the available types, fields, arguments, and relationships, while the server implementation provides the logic for resolving fields.
- SDL defines the structure and capabilities of a GraphQL API in a readable format.
- Its type definitions help validate operations and input values against the schema.
- It supports schema documentation and development tools, depending on the server and tooling used.
Defining Types in GraphQL
GraphQL SDL supports six kinds of named type definitions: scalar, object, enum, interface, union, and input object. It also provides list and non-null modifiers to specify collection and nullability rules.
1. Scalar Types
Scalar types represent individual values that do not have subfields. GraphQL provides five built-in scalar types:
- Int: A signed 32-bit integer.
- Float: A signed double-precision floating-point value.
- String: A UTF-8 character sequence.
- Boolean: Represents true or false.
- ID: Represents an identifier, commonly used to identify an object. It is serialized like a string and is not intended to be human-readable.
Example:
type Example {
name: String
}
The name field returns a scalar string value. GraphQL also supports custom scalars, such as DateTime, whose serialization and validation behavior must be defined by the server implementation.
2. Object Types
Object types describe structured data through fields and their corresponding types. Fields can return scalars, enums, other objects, interfaces, unions, or lists of these types.
Example:
type User {
id: ID!
name: String!
age: Int
}
The User type defines three fields. The id and name fields are non-null, while age is nullable because its type does not include the ! modifier.
3. Input Object Types
Input object types group related values into a structured input. They can be used for field arguments and variables, such as the data supplied to a mutation. Unlike object types, input object types cannot be used as output types.
Example:
input UserInput {
name: String!
age: Int
}
The UserInput type defines the values accepted by an operation that uses this input. The name value is non-null, while age can be null or omitted when the input is supplied.
4. List and Non-Null Types
GraphQL uses two type modifiers to define collections and nullability:
- List ([]): Specifies a list of values of the given type.
- Non-null (!): Specifies that a value cannot be null.
Example:
type Post {
title: String!
tags: [String]
}
The title field cannot be null. The tags field can return a null list, and its list items can also be null.
Different combinations of list and non-null modifiers provide different constraints:
| Type | Meaning |
|---|---|
| [String] | The list and its items can be null. |
| [String!] | The list can be null, but its items cannot. |
| [String]! | The list cannot be null, but its items can. |
| [String!]! | Neither the list nor its items can be null. |
A non-null list can still be empty. The ! modifier does not require at least one item.
5. Enum Types
Enum types define a fixed set of allowed values. They are useful when a field or argument must accept one value from a predefined set.
Example:
enum UserRole {
ADMIN
USER
GUEST
}
type User {
role: UserRole
}
The role field can use one of the values defined by UserRole. Since the field is nullable, it can also return null.
6. Interface and Union Types
Interfaces and unions are abstract types that allow a field to return different object types.
- Interface: Defines common fields that implementing object types must provide with compatible types.
- Union: Defines a set of possible object types without declaring common fields.
Example:
interface Animal {
name: String!
}
type Dog implements Animal {
name: String!
barkVolume: Int
}
type Cat implements Animal {
name: String!
livesRemaining: Int
}
union Pet = Dog | Cat
Both Dog and Cat implement the Animal interface by providing the required name field. The Pet union can represent either object type. Clients can use inline fragments to request fields specific to Dog or Cat.
7. Root Operation Types
GraphQL SDL defines the entry points through which clients interact with an API. These entry points are object types with special roles in the schema.
- Query: Defines fields for retrieving data. A GraphQL schema must have a query root type.
- Mutation: Defines fields for modifying data and is optional.
- Subscription: Defines fields for receiving event-based updates and is optional.
Example:
type Query {
user(id: ID!): User
}
type Mutation {
createUser(input: UserInput!): User!
}
The Query type defines a field for retrieving a user by ID. The Mutation type defines an operation for creating a user from a UserInput value. In common schemas, the root types are named Query, Mutation, and Subscription; custom names can be specified through a schema definition.
8. Schema Descriptions and Directives
SDL also supports descriptions and directives that add information or specify behavior for schema elements.
- Descriptions: Document types, fields, and arguments. Supported schema tools can display these descriptions to developers.
- Directives: Use the @ prefix to annotate schema elements or operations. Their effects depend on the directive and its supported locations.
Example:
type User {
displayName: String!
name: String @deprecated(reason: "Use displayName instead.")
}
The @deprecated directive marks name as deprecated and tells developers to use displayName instead. The existing field can remain available for compatibility.
Benefits of GraphQL SDL
- Readability: Provides a clear, language-independent description of the API schema.
- Schema validation: Enables GraphQL implementations to check operations and input values against declared types.
- Developer tooling: Supported tools can use schema definitions for validation, code generation, and editor assistance.
- Documentation: Descriptions can help document schema elements and can be exposed through introspection when available.