💁‍♂️

[GraphQL] Union 型をクエリするドキュメントの書き方

2023/05/18に公開
union SearchResult = Photo | Person

type Person {
  name: String
  age: Int
}

type Photo {
  height: Int
  width: Int
}

type SearchQuery {
  firstSearchResult: SearchResult
}

という定義があったとき、SearchQuery のドキュメントは

{
  firstSearchResult {
    ... on Person {
      name
    }
    ... on Photo {
      height
    }
  }
}

のようになる。
❌ このようには書けない(name を持つ型である Person が返ることが保証できない)

{
  firstSearchResult {
    name
  }
}

ref.
GraphQL Spec
https://spec.graphql.org/October2021/#sec-Unions


ここで仮に、

union SearchResult = Photo | Person

type Person {
  name: String
  age: Int
  status: PersonStatus # ←追加
}

enum PersonStatus {
  INVITED
  ACTIVE
  LEFT
}

type Photo {
  height: Int
  width: Int
  status: PhotoStatus # ←追加
}

enum PhotoStatus {
  PUBLIC
  PRIVATE
}

となった(どちらも型の異なる status プロパティを持つ)場合、
❌ 静的型付け言語のライブラリではこのようなドキュメントは書けないことが多いらしい。

{
  firstSearchResult {
    ... on Person {
      status
    }
    ... on Photo {
      status
    }
  }
}

その場合、
👎 このような書き方ができるらしいが、あまり推奨はできない。

{
  firstSearchResult {
    ... on Person {
      personStatus: status
    }
    ... on Photo {
      photoStatus: status
    }
  }
}

エイリアスを設定するか、素直にリネームをしたほうがいいらしい。
https://github.com/graphql/graphql-js/issues/522#issuecomment-255837127


ちなみに、これは書けることが多い。(name が同じ型 String なので)

union SearchResult = Photo | Person

type Person {
  name: String
  age: Int
}

type Photo {
  name: String # ←追加
  height: Int
  width: Int
}
{
  firstSearchResult {
    ... on Person {
      personName: name
    }
    ... on Photo {
      photoName: name
    }
  }
}

Discussion