You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GraphQL创建查询关联报错:Cannot access 'CategoryType' before initialization

Fixing "ReferenceError: Cannot access 'CategoryType' before initialization" in GraphQL

Hey there! Let's break down what's causing this error and how to fix it, plus why that YouTube course code worked when yours didn't.

Why the Error Happens

In JavaScript, variables declared with const (and let) have a "temporal dead zone"—you can't access them before they're fully initialized. In your code, you’re trying to use CategoryType inside ProductType’s fields, but CategoryType isn’t defined yet (it’s declared after ProductType). That’s exactly why the runtime throws this reference error.

Why the YouTube Course Code Worked

Chances are the course used a workaround you might have missed:

  • Function-based fields: They probably set the fields property as a function (not an object). Functions run later, after all types have been declared, so circular references don’t break things.
  • Separated type definitions & resolvers: Many modern GraphQL setups (like Apollo Server) use SDL (Schema Definition Language) for types and separate resolver functions, which avoids this circular reference issue entirely.
  • Hoisted function declarations: If they used function-based type creators (less common with vanilla GraphQL.js), function declarations are hoisted—meaning they can be referenced before they’re defined.

How to Fix Your Code

The simplest fix for vanilla GraphQL.js is to turn your fields objects into functions that return objects. This delays the evaluation of type references until both types are initialized. Also, I spotted a small issue: your CategoryType’s products field should use GraphQLList(ProductType) (since a category has multiple products—your current code uses just ProductType, which would cause type mismatches when Product.find() returns an array).

Here’s the corrected code:

const ProductType = new GraphQLObjectType({
  name: 'Product',
  fields: () => ({ // Convert fields to a function
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    category: {
      type: CategoryType,
      resolve: async (parent) => {
        return await Category.findOne({_id: parent.category});
      }
    }
  })
});

const CategoryType = new GraphQLObjectType({
  name: 'Category',
  fields: () => ({ // Convert fields to a function
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    products: {
      type: new GraphQLList(ProductType), // Fix: use GraphQLList for multiple products
      resolve: async (parent, args) => {
        return await Product.find({category: parent._id});
      }
    }
  })
});

const Query = new GraphQLObjectType({
  name: 'Query',
  fields: {
    Categories: {
      type: new GraphQLList(CategoryType),
      resolve: async () => {
        return await Category.find();
      }
    }
  }
});

This works because GraphQL.js calls the fields functions after all your type variables are initialized—so CategoryType exists when ProductType’s fields are evaluated, and vice versa.

内容的提问来源于stack exchange,提问作者Dory Miller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 14:22:32