ExpressのGraphQLで相互のRelation関係にあるTypeをimportする方法

ExpressでGraphQLを実装している時に、TypeでRelationの関係を作ろうとして

Error: Expected undefined to be a GraphQL type

というエラーに出会いました。

原因はType同士でimportしていたために、一方のTypeがundefinedになってしまうことです。

この問題に対応してみました。

GraphQLのType同士で循環参照する場合

まず今回エラーが発生したコードは書きのようなものです。

それぞれのTypeからお互いをimportしています。

import UserType from './UserType';

const PostType = new GraphQLObjectType({
  name: 'Post',
  fields: {
    title: { type: GraphQLString },
    user: { type: UserType }
  }
});

export default PostType;
import PostType from './PostType';

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: {
    name: { type: GraphQLString },
    posts: { type: new GraphQLList(PostType) }
  }
});

export default UserType;

お互いをimportしている循環参照の関係にあるため、当然ですがこのコードでは先に読み込まれる方が、読み込み先のTypeをundefinedとして認識します。

ただGraphQLでTypeを定義しているとこういうコードは避けられないと思う一方で、どういう風に対策するのがよいのか。

fieldsではオブジェクトではなく関数で返す

fieldsはオブジェクトではなく、オブジェクトを関数を指定することができます。

関数で返すことをfieldsの部分が遅延評価されるようになり、先に書いたように読み込んだ時点ではundefinedでもエラーが発生しなくなります。

コードとしては下記のような形です。

const PostType = new GraphQLObjectType({
  name: 'Post',
  fields: {
    title: { type: GraphQLString },
    user: { type: UserType }
  }
});

export default PostType;
const UserType = new GraphQLObjectType({
  name: 'User',
  fields: {
    name: { type: GraphQLString },
    posts: { type: new GraphQLList(PostType) }
  }
});

export default UserType;

わかってしまえばなんてことないけど、少しハマってしまいました・・。

この記事を書いた人

コウジ

TypeScriptとVue.jsが好きなフリーランスのフロントエンドエンジニアです。
フロントのHTML・CSS・JavaScriptの設計実装をメインに、RubyとNodeでサーバーサイドやってたりもします。

Web開発の仕事依頼

フリーランスのエンジニアとしてWeb開発の仕事をお引き受けしています。

依頼の検討をしていただきます際はポートフォリオサイトの事業・実績ページをご覧いただき、お問い合わせよりメールや各種SNSよりご連絡ください。

仕事の相談をする
基礎から学ぶ Vue.js