かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

GraphQL 複数の型が含まれる配列の Schema を定義したい

GraphQL で A 又は B が含まれる配列を返す schema を作成したかったのでメモ

  1. A型 または Bの型を返す Union Type を作成する
  2. Union Type が含まれる配列の型を作成する

1. A型 または Bの型を返す Union Type を作成する

  • union キーワードで定義する
  • Union Type は object types しか取ることができない

Union 型にするためのオブジェクト型をそれぞれ定義する必要がある

type Unit {
  id: ID!
  name: String!
}

enum IdolType {
  cute
  cool
  pop
  sexy
}

type Idol {
  id: ID!
  name: String!
  type: IdolType!
}

# Union 型の定義
union UnitOrIdol = Unit | Idol

# Union 型を返す query
type Query {
  unitOrIdol: UnitOrIdol!
}

Union Type を取得する Query

... on で Union の型ごとのフィールドを指定する

query GetUnitOrIdol {
  unitOrIdol: {
    ... on Unit {
      id
      name
    }
    ... on Idol {
      id
      name
      type
    }
  }
}
Code Generator で生成された型
export type Unit = {
  __typename?: 'Unit';
  id: Scalars['ID'];
  name: Scalars['String'];
};

export type Idol = {
  __typename?: 'Idol';
  id: Scalars['ID'];
  name: Scalars['String'];
  type: IdolType;
};

export enum IdolType {
  Cool = 'cool',
  Cute = 'cute',
  Pop = 'pop',
  Sexy = 'sexy',
}

export type UnitOrIdol = Idol | Unit;

export type GetUnitOrIdolQuery = {
  __typename?: 'Query';
  unitOrIdol:
    | { __typename?: 'Idol'; id: string; name: string; type: IdolType }
    | { __typename?: 'Unit'; id: string; name: string };
};

Query の型は単純にオブジェクトの Union 型になっていました。

2. Union Type が含まれる配列の型を作成する

いずれかの型が含まれる配列は単に Union Type の配列と定義すれば良い

# Union 型の定義
union UnitOrIdol = Unit | Idol

# Union 型を返す query
type Query {
- unitOrIdol: UnitOrIdol!
+ unitOrIdol: [UnitOrIdol!]!
}

呼び出す側の Query は特に変更はない

Code Generator で生成された型

Query を投げた際に返却されるデータの schema が変化しているので GetUnitOrIdolQueryunitOrIdol キーの値が配列になるよう変更されている

export type GetUnitOrIdolQuery = {
  __typename?: 'Query';
  unitOrIdol: Array<
    | { __typename?: 'Idol'; id: string; name: string; type: IdolType }
    | { __typename?: 'Unit'; id: string; name: string }
  >;
};

これで GprahQL で複数の型が含まれる配列の型を定義することができました。

所管

GraphQL まだまだ雰囲気で使っているので勉強しないとな〜と痛感しています。
GraphQL の Union Type はオブジェクトしか指定できないようなので String | Int のようなスカラー値の Union 型や [ {A: 'a'}, 'foo', ... ] のようなオブジェクトか文字列が含まれる配列のような schema は定義できないっぽい?という認識なのですが誤りがあればご指摘ください 🙏


[参考]