The GraphQL Type System In Depth
Every GraphQL API is described by a schema written in the Schema Definition Language (SDL), and that schema is really a graph of typed nodes: object types, scalar types, enums, interfaces, unions, and input types, all wired together by fields. The type system is the contract between client and server — a client can only ask for fields that exist on a type, and the server guarantees the shape of the response before a single resolver runs, because the query is validated against the schema first.
Cricket analogy: Just as a scorecard format is fixed before a match starts — runs, wickets, overs, extras — the GraphQL schema fixes exactly which fields a type like Batsman can expose, so a client can't suddenly ask for a field that was never defined, like 'astrologicalSign'.
Scalars and Object Types
GraphQL ships with five built-in scalar types — Int, Float, String, Boolean, and ID — which represent the leaf nodes of any query; you cannot select sub-fields on a scalar because it has no internal structure. Object types, defined with the type keyword, are the composite nodes: they group named, typed fields, and every field on an object type must itself resolve to either a scalar, an enum, or another object/interface/union, forming the graph that gives GraphQL its name.
Cricket analogy: A player's strike rate (a Float) is a terminal number you can't drill into further, whereas the Player object type itself has sub-fields like battingStyle and team that you can keep expanding, just like scalar versus object types in GraphQL.
Input Types and List Modifiers
Input types, declared with input rather than type, exist purely for arguments — they can't have fields that resolve to interfaces or unions, only scalars, enums, and other input types, because the server needs to deserialize them from the query variables without any resolution logic. List modifiers ([Type]) and non-null modifiers (Type!) wrap around any of these building blocks, so a field's full signature, like tags: [String!]!, precisely encodes 'a non-null list of non-null strings.'
Cricket analogy: A DRS (Decision Review System) review request form only takes fixed inputs — team, over number, delivery — nothing resolved from live match state, just as a GraphQL input type only carries plain data, never resolved object/interface fields.
type Player {
id: ID!
name: String!
strikeRate: Float
team: Team!
battingStyle: BattingStyle
}
input PlayerFilter {
minStrikeRate: Float
team: ID
battingStyle: BattingStyle
}
type Query {
players(filter: PlayerFilter, limit: Int = 10): [Player!]!
}The introspection system (__schema, __type) is itself built entirely from the type system — tools like GraphiQL and Apollo Studio query __schema to render documentation, which is why a well-described schema (using SDL description strings) pays off directly in tooling quality.
Renaming or removing a field is a breaking change for any client that selects it — because validation happens against the current schema, an old query referencing a deleted field fails outright rather than silently returning null. Use deprecation (@deprecated(reason: "...")) and a migration window instead of deleting fields outright.
- GraphQL schemas are graphs of typed nodes connected by fields, written in SDL.
- The five built-in scalars (Int, Float, String, Boolean, ID) are the only leaf types with no sub-selections.
- Object types group named fields that resolve to scalars, enums, or other object/interface/union types.
- Input types are argument-only structures restricted to scalars, enums, and other input types.
- List (
[Type]) and non-null (Type!) modifiers combine to precisely encode a field's nullability and cardinality. - Queries are validated against the schema before execution, so undeclared fields are rejected immediately.
- Introspection (
__schema,__type) exposes the type system itself, powering docs and IDE tooling.
Practice what you learned
1. Which of these is NOT one of GraphQL's built-in scalar types?
2. What restriction applies to fields on a GraphQL `input` type?
3. What does the field signature `tags: [String!]!` mean?
4. When does GraphQL validate that a queried field actually exists on a type?
5. What GraphQL mechanism lets tools like GraphiQL auto-generate documentation and autocomplete?
Was this page helpful?
You May Also Like
Interfaces and Unions
How GraphQL's two abstract types — interfaces with guaranteed shared fields, and unions with no shared contract — let a single field return polymorphic results.
Enums in GraphQL
How GraphQL enums restrict fields and arguments to a fixed, validated set of named values, and how their SDL names map to internal server representations.
Nullable vs Non-Nullable Types
Why fields are nullable by default in GraphQL, what the `!` modifier guarantees, and how null bubbling propagates a single resolver failure up the response tree.
Custom Scalars
How to model domain-specific leaf values beyond GraphQL's five built-in scalars using serialize, parseValue, and parseLiteral.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics