skip to content

In GraphQL SDL, what is the difference between an interface type and a union type?

level: juniorimportance: must knowfreq 74%

answer

  1. Two abstract output types, one difference
  2. One of them declares fields
  3. The other only lists members
  4. Members are object types only
  5. Implementer opts in; union names its members

basics

~20 s

An interface declares fields that every implementing object type must declare too, so a client can select those shared fields on the abstract type itself. A union declares no fields at all — it only lists which object types the value may be.

solid answer

~50 s

Both are abstract output types: the declared type of a field, standing for one of several concrete object types. The difference is that an **interface is a field contract** and a **union is a membership list**. An interface names one or more fields; an object type that writes `implements RegistryRecord` must declare every one of those fields itself, and the schema fails to build if it does not. Because those fields are declared on the interface, a client can select them without knowing which concrete type it got. A union — `union SearchResult = Trial | Site | Investigator` — declares nothing but its members, so there is no shared field to select and every real field has to be asked for per member type. Union members must be object types; interfaces are implemented by object types and, since the October 2021 specification edition, by other interfaces.

code

graphql · 28 lines
graphql
interface RegistryRecord {
  id: ID!
  registeredOn: String!
}

type Trial implements RegistryRecord {
  id: ID!
  registeredOn: String!
  phase: TrialPhase!
}

type Site implements RegistryRecord {
  id: ID!
  registeredOn: String!
  country: String!
}

type Investigator {
  id: ID!
  fullName: String!
}

union SearchResult = Trial | Site | Investigator

type Query {
  timeline(limit: Int = 20): [RegistryRecord!]!
  search(term: String!): [SearchResult!]!
}

go deeper

for a junior

Be ready to state the difference in one sentence and give an example of each. Remember that an interface lists fields and a union lists object types, and that implementing types repeat the interface's fields in their own definition.

for a middle

An interviewer expects the exact member rules: object types only in a union, no duplicates, at least one member; at least one field on an interface; both output-only. Explain why a union forces a client to ask per member type.

for a senior

Show that you know membership is declared from opposite ends — implementers opt into an interface, while a union names its members in one place — and what that means for who can extend the graph without coordinating.

for a principal

Own the framing: an interface is a promise you are making on behalf of every future implementer, a union is a list one team edits. Be able to say which shape you want a domain's extension points to have and why.

## GraphQL has exactly two abstract output types Most fields in a schema have a concrete type: `phase: TrialPhase!` will always be that enum, `site: Site!` will always be that object type. An **abstract type** says something weaker — the value will be *one of* several object types, and which one is decided while the request executes. GraphQL spells that two ways, interfaces and unions, and they differ in one respect that drives every other difference: **an interface declares fields; a union declares none.** ## The interface: a contract each implementer restates ```graphql interface RegistryRecord { id: ID! registeredOn: String! } type Trial implements RegistryRecord { id: ID! registeredOn: String! phase: TrialPhase! } ``` An interface is a named set of field declarations. It must declare at least one field. An object type opts in with an `implements` clause, and opting in obliges it to declare every one of those fields on itself — there is no inheritance in the SDL text, the declarations are physically repeated. That obligation is checked when the server builds the schema, so a type that quietly omits `registeredOn` produces a build-time schema error, not a surprise at runtime. The payoff is on the client side. Because `id` and `registeredOn` are declared *on the interface*, a field typed `RegistryRecord` can be asked for them directly, whatever concrete type comes back. A registry timeline that shows "what was registered, and when" over trials, sites and protocols is one selection, not three. An object type may implement several interfaces at once (`type Trial implements RegistryRecord & Auditable`), and an interface may have any number of implementers. Since the October 2021 edition of the specification, an interface may itself implement another interface, which lets you express a narrower contract that refines a broader one; older servers may not support that, so check before relying on it. ## The union: a set whose members share nothing ```graphql union SearchResult = Trial | Site | Investigator ``` That is the whole declaration. There is no field list, because the union makes no claim that its members have anything in common — only that this one field may return any of them. Registry search is the archetype: a query box over a clinical-trial registry returns trials, sites and investigators, and those three genuinely share no meaningful field. The rules are short and worth knowing exactly: - Members must be **object types**. An interface, another union, a scalar, an enum or an input object may not be a member. - A union must have at least one member, and a member may not be listed twice. - Members declare nothing. `Trial` has no idea it is in `SearchResult`; the union names it, not the other way round. Because the union declares no fields, there is nothing to select on it directly except the meta-field that reports the concrete type name. Every real field has to be requested per member type. That is the practical cost of a union, and it is the difference an interviewer is usually listening for. ## Membership is declared from opposite ends This is the second-order difference, and it is the one that shows up in a design review. An interface is opted *into* by the implementer, so a part of the schema you have not written yet can add an implementer without anyone touching the interface — the set is open. A union is a closed list, edited in exactly one place, so the set is only as open as the team that owns that one line. Neither is better; they are different governance shapes for "this field may return several things". ## Both are output-only, and neither is the other Interfaces and unions are output types. Neither can appear where an input type is required. A union cannot be implemented, and an interface cannot be a union member — the two mechanisms do not compose in that direction. What they do share is that the concrete type of each returned value has to be worked out by the server during execution, and that clients get at concrete-type fields by narrowing to a specific type; both of those are their own topics, and neither changes the SDL-level distinction here. ## The one-line test Ask whether the alternatives share fields a client should be able to read *without caring which one it got*. If yes, that shared set is an interface, and the interface is worth its cost. If the only thing the alternatives have in common is that this single field may return any of them, it is a union, and inventing an interface to unify them will produce a contract full of fields that are meaningless for half the implementers.

  • Can a union include an interface type or a scalar among its members?
    No. Union members must be object types — an interface, another union, a scalar, an enum or an input object is invalid there, and a duplicate member is invalid too. If the members do share a field you want selectable across the whole set, that shared set is what an interface is for; a union deliberately makes no such claim.
  • Can one object type implement more than one interface, and what does that oblige it to do?
    Yes — the implements clause takes several interfaces separated by `&`, as in `type Trial implements RegistryRecord & Auditable`. The type must then declare every field of every interface it names, each with a compatible type and the same arguments. There is no limit on how many it implements, and interfaces may overlap in the fields they require as long as the declarations agree.
  • Must an interface declare at least one field, and must a union have at least one member?
    Yes on both counts. An interface with an empty field list is an invalid type definition, and so is a union with no members — the schema fails to build. An empty interface would in any case be pointless: its whole value is the fields it lets a client select on the abstract type.

An interface is a job description every hire must satisfy before they are counted; a union is a guest list — the names are on it, but nobody asked the guests to have anything in common.

saying these in an interview costs you the question

  • Calls a union a base class implementers extend
  • Thinks a union can list interfaces or scalars
  • Claims implementers inherit interface fields without redeclaring
  • Says shared fields can be selected directly on a union
  • Believes a member type declares which unions it joins
  • Treats interface and union as interchangeable spellings

context