100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
GraphQL

Scalar and Object Types

A deep dive into GraphQL's built-in scalar types, custom scalars, enums, and how object types compose the graph.

GraphQL FoundationsBeginner8 min readJul 10, 2026
Analogies

Scalar and Object Types

Every field in a GraphQL schema ultimately resolves to a scalar type at its leaves — a concrete, indivisible value like a string or number — even when the field itself returns a complex object type. GraphQL ships with five built-in scalars: String for UTF-8 text, Int for signed 32-bit integers, Float for signed double-precision floating point numbers, Boolean for true/false, and ID for a unique identifier that is serialized as a string but signals semantic intent, such as being used as a cache key or lookup argument rather than displayed text.

🏏

Cricket analogy: A scalar is like a single stat on a scorecard — the number 87 for runs scored is an indivisible value, unlike the batter's full profile which is a composite object type.

The Five Built-In Scalars

The ID scalar deserves special attention because it looks identical to String on the wire — both serialize as JSON strings — but it carries semantic meaning that tooling relies on: normalized caches in Apollo Client and Relay use a type's id field combined with its type name to uniquely identify and deduplicate objects across different queries, and GraphQL's Relay-style global object identification convention is built entirely around a well-defined ID field. Choosing Int versus Float also matters for precision-sensitive domains: a warehouse inventory count should be Int, while a geographic coordinate is typically modeled as Float, though many schemas use a custom Decimal or Money scalar instead of Float for currency to avoid floating-point rounding errors.

🏏

Cricket analogy: Treating a player's ID scalar like their unique BCCI registration number rather than just their display name lets a stats app deduplicate 'V Kohli' records pulled from different match feeds into one player object.

graphql
scalar DateTime

enum OrderStatus {
  PENDING
  SHIPPED
  DELIVERED
  CANCELLED
}

type Order {
  id: ID!
  placedAt: DateTime!
  status: OrderStatus!
  totalCents: Int!
}

Custom Scalars and Enums

Beyond the five built-ins, GraphQL lets servers define custom scalars for domain-specific values that need their own serialization logic, the most common example being a DateTime scalar for ISO-8601 timestamps; implementing one requires providing serialize (converting the internal value to a JSON-safe form for the response), parseValue (converting an incoming JSON value from a variable), and parseLiteral (converting an inline value written directly in the query text) functions. Enums are a related but distinct concept: an enum type restricts a field to one of a fixed set of named values, such as enum OrderStatus { PENDING, SHIPPED, DELIVERED, CANCELLED }, giving both the schema and generated client types a closed, self-documenting set of valid options instead of an unconstrained string.

🏏

Cricket analogy: A custom DateTime scalar for a match's toss time is like the ICC standardizing all match timestamps to UTC in official records, while an enum for MatchResult (WON, LOST, TIED, NO_RESULT) mirrors cricket's own fixed, official set of outcome labels.

Implementing a custom scalar requires three functions — serialize, parseValue, and parseLiteral — but you rarely need to write these from scratch: libraries like graphql-scalars already ship battle-tested implementations for DateTime, EmailAddress, URL, and dozens of other common domain types.

Object Types Build the Graph

Object types become genuinely powerful when their fields reference other object types rather than only scalars: a Book type can have an author field of type Author, and Author can have a books field of type [Book!]!, creating a graph with a real cycle that a client can traverse in either direction within a single query — fetching a book's author and that author's other books in one round trip. This is the structural feature GraphQL is named for, but it also means a resolver for a nested object field runs independently for each parent item, so naively resolving each Book's Author with a separate database call inside a loop produces the classic N+1 query problem, which is why production servers typically batch and cache these lookups using a tool like DataLoader.

🏏

Cricket analogy: A Player type with a team field of type Team, and Team with a players field of type [Player!]!, lets a client fetch Kohli's team and then that team's full squad in one traversal, mirroring how a cricket almanac cross-references player and team pages.

Resolving nested object fields naively — issuing one database query per item inside a loop, such as fetching each Book's Author one at a time — produces the classic N+1 query problem. Batch and cache these lookups per request with a tool like DataLoader to collapse them into a single query.

  • Scalars are indivisible leaf values; GraphQL's five built-ins are String, Int, Float, Boolean, and ID.
  • ID looks like String on the wire but signals semantic intent used by caching and global object identification.
  • Custom scalars (like DateTime or Money) need serialize, parseValue, and parseLiteral functions, often provided by libraries like graphql-scalars.
  • Enums restrict a field to a fixed, named set of values, giving a closed and self-documenting alternative to plain strings.
  • Object types reference other object types, forming the actual graph structure GraphQL is named for.
  • Naively resolving nested object fields in a loop causes the N+1 query problem; DataLoader batches and caches these lookups.

Practice what you learned

Was this page helpful?

Topics covered

#GraphQL#GraphQLStudyNotes#WebDevelopment#ScalarAndObjectTypes#Scalar#Object#Types#Five#OOP#APIs#StudyNotes#SkillVeris