GraphQLを使用する開発者にとって、「Expected type X got type Y」というエラーメッセージは比較的よく遭遇する問題です。このエラーは、GraphQLスキーマで定義されたデータ型と、実際に提供されたデータ型が一致しない場合に発生します。本記事では、このエラーの原因と解決方法について詳しく解説します。

エラーの原因

「Expected type X got type Y」エラーの主な原因は以下の通りです:

1. クエリやミューテーションの引数の型が間違っている

2. リゾルバー関数が誤った型のデータを返している

3. スキーマ定義と実装の不一致

解決方法

1. クエリやミューテーションの確認

まず、クライアント側で送信しているクエリやミューテーションを確認しましょう。引数の型が正しいかどうかを確認し、必要に応じて修正します。

例:

# 間違い
mutation {
  createUser(name: 123, age: "30") {
    id
    name
  }
}

# 正しい
mutation {
  createUser(name: "John Doe", age: 30) {
    id
    name
  }
}

2. リゾルバー関数の確認

サーバー側のリゾルバー関数が正しい型のデータを返しているか確認します。特に、非同期操作や外部APIからのデータ取得を行っている場合は注意が必要です。

例:

// 間違い
const resolvers = {
  Query: {
    user: () => {
      return { id: "1", name: 123 }; // nameが数値型になっている
    }
  }
};

// 正しい
const resolvers = {
  Query: {
    user: () => {
      return { id: "1", name: "John Doe" };
    }
  }
};

3. スキーマ定義の確認

GraphQLスキーマ定義が正しいか、実装と一致しているか確認します。特に、カスタム型や列挙型を使用している場合は注意が必要です。

例:

# スキーマ定義
type User {
  id: ID!
  name: String!
  age: Int
}

# クエリ定義
type Query {
  user(id: ID!): User
}

4. Nullableフィールドの扱い

必須フィールド(Non-Null)と任意フィールド(Nullable)の区別に注意しましょう。スキーマで`!`が付いているフィールドには、必ず値を設定する必要があります。

5. 型変換の実装

場合によっては、データの型を適切に変換する必要があります。例えば、文字列として受け取った数値を、整数型に変換するなどです。

const resolvers = {
  Query: {
    user: (_, { id }) => {
      const user = fetchUserFromDatabase(id);
      return {
        ...user,
        age: user.age ? parseInt(user.age, 10) : null
      };
    }
  }
};

6. デバッグツールの活用

GraphQL Playground やApollo Studio などのツールを使用して、クエリの実行結果やエラーメッセージを詳細に確認することができます。これらのツールを活用して、問題の原因を特定しやすくなります。

まとめ

「Expected type X got type Y」エラーは、GraphQLの型システムに関連する問題です。このエラーを解決するには、クエリ、リゾルバー、スキーマ定義の三つの要素を慎重に確認し、必要に応じて修正を行うことが重要です。適切なデバッグツールの使用と、型の一貫性を保つことで、より堅牢なGraphQLアプリケーションを開発することができます。