Graphql: typechecking loop error with circular node reference

Created on 19 Nov 2017  路  5Comments  路  Source: graphql-go/graphql

I'm hitting a wall while trying to build an API with circular references between types.

A simplified example of my types looks like this:

Role {
  Company
  Employee
}
Employee {
  roles List(Role)
}

Attempting to create this results in a typechecking loop error from the go compiler.

This seems to be a result of the employeeType referencing roleType which in turn references employeeType again.

I would expect these kinds of models to be central to a Graph API. Is there a better way to be building this?

Thanks for any feedback.

Most helpful comment

Ok, the issue is because a type-switch is being used to identify whether a thunk is being used, and my closure was not statically typed as FieldsThunk, the correct example is:

var SomeType graphql.Type

func init() {
    SomeType = graphql.NewObject(graphql.ObjectConfig{
        Name: "SomeType",
        Fields: graphql.FieldsThunk(func() graphql.Fields { // notice func here
            return graphql.Fields{
                "circularRef": {
                    Type: Environment,
                },
            }
        }),
    })
}

All 5 comments

Looks like "field thunks" are the way to do this. The graphql.ObjectConfig.Fields field can be a function which is evaluated lazily, rather than a map[string]Field.

Using field thunks along with moving the definition into an init() function seems to do the trick.

var SomeType graphql.Type

func init() {
    SomeType = graphql.NewObject(graphql.ObjectConfig{
        Name: "SomeType",
        Fields: func() graphql.Fields { // notice func here
            return graphql.Fields{
                "circularRef": {
                    Type: Environment,
                },
            }
        },
    })
}

Update: I may have spoken too soon, I'm now getting a runtime error:

fields must be an object with field names as keys or a function which return such an object

Ok, the issue is because a type-switch is being used to identify whether a thunk is being used, and my closure was not statically typed as FieldsThunk, the correct example is:

var SomeType graphql.Type

func init() {
    SomeType = graphql.NewObject(graphql.ObjectConfig{
        Name: "SomeType",
        Fields: graphql.FieldsThunk(func() graphql.Fields { // notice func here
            return graphql.Fields{
                "circularRef": {
                    Type: Environment,
                },
            }
        }),
    })
}

You're a lifesaver, mate! Thank you. Closing the issue as this solution resolved it.

As a side note, another way to do this is with Object.addFieldConfig. I've always done it this way in the past, creating partial types for each and then adding the circular fields afterwards.

there is a problem with FieldThunk and AddFieldConfig, if your object's fields returned by FieldThunk, you can't dynamically add field into your object by AddFieldConfig. I ran into this problem because I restruct my project's fields/types/schema module.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

titanous picture titanous  路  3Comments

FrontMage picture FrontMage  路  5Comments

yookoala picture yookoala  路  4Comments

jiharal picture jiharal  路  5Comments

SDkie picture SDkie  路  6Comments