Interfaces and unions#

Meta: these align directly with GraphQL interfaces and unions, so users coming from a schema will recognize them. Worth saying that up front to set expectations.

Interfaces#

Declaration#

interface Named {
  name: String!
}

Implementation#

type Person implements Named {
  name: String!
  age: Int!
}

Interface inheritance#

interface User implements Named { email: String! }
interface Post implements Named & Timestamped { title: String! }

Variance#

Pattern-matching an interface#

case (n) {
  p: Person => p.age
  c: Company => c.size
  fallback: Named => fallback.name
}

Unions#

Declaration#

union Pet = Cat | Dog

Discriminating#

case (pet) {
  c: Cat => c.purr
  d: Dog => d.bark
}

Inline fragments#

Meta: inline fragments are selection syntax, so the full treatment — the field-selecting form, the lazy narrowing form, null/assertion behavior — lives with the rest of selection in GraphQL interop. Keep this as a pointer, not a second copy.

pets.{{
  ... on Cat { name, lives }
  ... on Dog { name, tricks }
}}

Interface vs. union vs. enum#

Meta: newcomers conflate these; a one-line contrast keeps them straight. (enums live in Enums and scalars.)

what it is members discriminate with open to extension
interface a shared field contract object/interface types that implement it case type patterns, inline fragments yes — any type can implement
union a closed set of object types object types only, listed explicitly case type patterns, inline fragments no — fixed member list
enum a closed set of named constants bare identifiers (RED) case value patterns no — fixed value list