Generics Support

Go generics allow you to write reusable, type-safe code. GQLSchemaGen understands generic types and automatically expands them in your GraphQL schema, making it easy to use generic patterns like Response[T], Paginated[T], or Result[T, E] in your API.


How It Works

When you use a generic type in an annotated struct, GQLSchemaGen:

  1. Detects the generic instantiation (e.g., Response[*User])
  2. Substitutes type parameters with concrete types
  3. Expands embedded generic structs inline
  4. Generates proper GraphQL types with resolved field types

Basic Example

response.go

Generated GraphQL:

schema.graphqls

The generic Response[T] is expanded inline, and T is replaced with User.


Multiple Type Parameters

Generics with multiple type parameters are fully supported:

result.go

Generated:

schema.graphqls

Nested Generic Types

Generics can be nested and combined:

paginated.go

Generated:

schema.graphqls

Notice how Edge[*Product] becomes ProductConnectionEdge - GQLSchemaGen generates unique type names for generic instantiations.


Auto-Generation with Generics

Auto-generation works seamlessly with generics:

gqlschemagen.yml
auto-gen.go

Both UserResponse and User are generated automatically.


Generic Type Naming

When GQLSchemaGen instantiates a generic type, it generates a unique name:

Pattern: {ParentType}{GenericType}{Index}

Examples:

  • Response[*User] embedded in UserResponse → Fields expanded inline in UserResponse
  • Edge[*Product] in slice → ProductConnectionEdge
  • Pair[*Key, *Value]TypePair (where Type is the parent)

This ensures each generic instantiation gets a unique, conflict-free type name.


Unresolved Type Parameters

If a generic type parameter cannot be resolved (e.g., standalone Result[T]), you can configure a fallback:

gqlschemagen.yml
unresolved.go

Options:

  • "" (empty) - Keep as-is, may cause out-of-scope warnings
  • "JSON" - Use JSON scalar
  • "Any" - Use Any scalar
  • Custom scalar name

Combining Generics with Annotations

You can use generic types alongside normal annotations:

combined.go

Generated:

schema.graphqls

Generic Constraints

Go generic constraints are respected:

constraints.go

Generated:

schema.graphqls

Best Practices

  1. Define generic types once: Reuse across multiple concrete types
  2. Use meaningful type parameters: T for data, E for errors, K/V for key/value
  3. Annotate concrete types: Put @gqlType on the concrete instantiation, not the generic definition
  4. Leverage auto-generation: Let GQLSchemaGen discover and generate referenced types
  5. Set unresolved fallback: Configure unresolved_generic_type to handle edge cases

Common Patterns

Response Wrapper

patterns.go

Paginated Results

pagination.go

Result Type (Either Pattern)

either.go

Limitations

  1. Generic definitions are not generated: Only concrete instantiations appear in the schema
  2. Type parameter inference: GQLSchemaGen uses actual type arguments, not inferred types
  3. Constraint checking: GraphQL schema doesn't enforce Go generic constraints

Once you've defined your generic types, run:

$ gqlschemagen generate

to generate GraphQL schemas with fully expanded generic types.