Skip to content
Graffle is a work in progress. Learn more.

Union

This example shows how to work with GraphQL union types in the TypeScript interface.

ts
// Our website uses Vitepress+Twoslash. Twoslash does not discover the generated Graffle modules.
// Perhaps we can configure Twoslash to include them. Until we figure that out, we have to
// explicitly import them like this.
import './graffle/modules/global.js'
// ---cut---

import { Graffle } from './graffle/$.js'

const pokemon = Graffle.create()

const battles = await pokemon.query.battles({
  __typename: true,
  ___on_BattleRoyale: {
    date: true,
    combatants: {
      trainer: {
        name: true,
      },
      pokemons: {
        name: true,
      }
    },
    winner: {
      name: true,
    },
  },
  ___on_BattleTrainer: {
    date: true,
    combatant1: {
      trainer: {
        name: true,
      },
      pokemon: {
        name: true,
      },
    },
    combatant2: {
      trainer: {
        name: true,
      },
      pokemon: {
        name: true,
      },
    },
    winner: {
      name: true,
    },
  },
  ___on_BattleWild: {
    date: true,
    trainer: {
      name: true,
    },
    pokemon: {
      name: true,
    },
    wildPokemons: {
      name: true,
    },
    result: true,
  },
})

// The following contrived switch console.logs how the returned type is a discriminated union.
// After checking the __typename, the type is known to be one of the possible battle types
// and TypeScript narrows accordingly.

const dateFormatter = new Intl.DateTimeFormat(`en-US`, { timeZone: `UTC` })

for (const battle of battles) {
  switch (battle.__typename) {
    case `BattleRoyale`: {
      const trainers = battle.combatants?.map(_ => _.trainer?.name)
      let info = ``
      info += `${battle.__typename} on ${dateFormatter.format(new Date(battle.date ?? 0))}\n`
      info += `combatants: ${trainers?.join(`, `) ?? `null`}\n`
      info += `winner: ${battle.winner?.name ?? `null`}`
      console.log(info)
      break
    }
    case `BattleTrainer`: {
      let info = ``
      info += `${battle.__typename} on ${dateFormatter.format(new Date(battle.date ?? 0))}\n`
      info += `${battle.combatant1?.trainer?.name ?? `null`} vs ${battle.combatant2?.trainer?.name ?? `null`}\n`
      info += `winner: ${battle.winner?.name ?? `null`}`
      console.log(info)
      break
    }
    case `BattleWild`: {
      let info = ``
      info += `${battle.__typename} on ${dateFormatter.format(new Date(battle.date ?? 0))}\n`
      info += `trainer: ${battle.trainer?.name ?? `null`} with ${battle.pokemon?.name ?? `null`}\n`
      info += `vs wild pokemons: ${battle.wildPokemons?.map(_ => _.name).join(`, `) ?? `null`}\n`
      info += `result: ${battle.result ?? `null`}`
      console.log(info)
      break
    }
  }
}

Outputs

txt
BattleWild on 1/1/2020
trainer: Ash with Pikachu
vs wild pokemons: Squirtle, Bulbasaur
result: pokemonsCaptured
txt
BattleTrainer on 1/1/2003
Ash vs Misty
winner: Misty
txt
BattleRoyale on 1/13/1987
combatants: Ash, Misty
winner: Ash

Released under the MIT License.