Skip to content

Fragments & Aliases

The last lesson of this module is about three tools that make queries cleaner rather than more powerful. Fragments let you name and reuse a selection set. Inline fragments let a selection branch on a type. Aliases let you rename a field in the response. None of them change what a server can do — they change how readable and flexible your queries are.

When the same set of fields shows up in more than one place, copying it everywhere is a maintenance trap. A fragment is a named selection set you define once and spread wherever you need it. You declare it with the fragment keyword, naming the type it applies to with on:

fragment TrackFields on Track {
id
title
durationSeconds
}

You then spread it into a selection set with the ... operator, as if its fields were written there directly:

{
track(id: "t1") {
...TrackFields
}
featured: track(id: "t2") {
...TrackFields
}
}

Both selections pull in id, title, and durationSeconds without repetition. Change the fragment in one place and every spread updates with it — the same payoff as factoring repeated code into a function.

Sometimes a field returns a type that could be one of several object types — an interface or a union. To select fields that only exist on one of those possibilities, you use an inline fragment: the ... operator followed by on SomeType and a selection set, with no name in between.

{
searchResult {
... on Track {
title
}
... on Artist {
name
}
}
}

Here searchResult might resolve to a Track or an Artist. The inline fragments say “if it is a Track, give me title; if it is an Artist, give me name.” Only the matching branch contributes to the response. Inline fragments are how you handle type branching inside a single selection.

flowchart TD
  Frag["fragment TrackFields on Track { id, title, durationSeconds }"]
  Frag -->|"... spread"| S1["hit: track(id: t1)"]
  Frag -->|"... spread"| S2["deepCut: track(id: t2)"]
  S1 --> R["Response with two aliased keys"]
  S2 --> R
A fragment is defined once and spread into many selections.

By default, a field appears in the response under its own name. An alias lets you choose a different key, written as aliasName: fieldName before the field. This is essential when you select the same field twice with different arguments — without aliases the two results would collide on the same key:

{
first: track(id: "t1") {
title
}
second: track(id: "t2") {
title
}
}

The response then has two distinct keys, first and second, each holding its own track. Aliases are purely about the shape of the response — they never touch the schema or the resolvers. They are also handy for adapting field names to whatever your client code expects.

The example below defines a TrackFields fragment, spreads it into two selections of the same track field, and uses aliases — hit and deepCut — so the two results sit under distinct keys. Press Run and read the response keys.

JavaScript

The response has two top-level keys, hit and deepCut, instead of one colliding track — that is the alias at work. Each holds the full set of fields from TrackFields, written once and reused twice — that is the fragment at work. Together they keep the query short and the response well-shaped.

What problem does a fragment solve?
When is an inline fragment like "... on Track" needed?
Why are aliases required when selecting the same field twice with different arguments?