Object types

Object types are the fundamentals of any GraphQL schema, they are used to define the kind of objects that exist in a schema. Object types are created by defining a name and a list of fields, here’s an example object type defined using the GraphQL schema language:

type Character {
  name: String!
  age: Int!
}

A note on Query, Mutation and Subscription

While reading about GraphQL you might have encountered 3 special object types: Query , Mutation and Subscription . They are defined as standard object types, with the difference that they are also used as entry points for your schema (also referred as root types).

For a walk-through on how to define schemas, read the schema basics .

Defining object types

In Strawberry, you can define object types by using the @strawberry.type decorator, like this:

import strawberry
 
 
@strawberry.type
class Character:
    name: str
    age: int
type Character {
  name: String!
  age: int!
}

You can also refer to other types, like this:

import strawberry
 
 
@strawberry.type
class Character:
    name: str
    age: int
 
 
@strawberry.type
class Book:
    title: str
    main_character: Character
type Character {
  name: String!
  age: Int!
}
 
type Book {
  title: String!
  mainCharacter: Character!
}

Object types can subclass other object types to reuse their fields, as long as the subclass is decorated too:

import strawberry
 
 
@strawberry.type
class Character:
    name: str
    age: int
 
 
@strawberry.type
class Wizard(Character):
    house: str
type Character {
  name: String!
  age: Int!
}
 
type Wizard {
  name: String!
  age: Int!
  house: String!
}

An undecorated subclass would be published as its parent type, without its own fields, so Strawberry raises an error when one is used in the schema. The same applies to input types and interfaces.

Customizing fields with Annotated

You can configure fields by adding strawberry.field() to typing.Annotated . This syntax works on object types, input types, and interfaces, including when using from __future__ import annotations :

from typing import Annotated
 
import strawberry
 
 
@strawberry.type
class User:
    name: Annotated[
        str,
        strawberry.field(name="displayName", description="The displayed name"),
    ]
    tags: Annotated[list[str], strawberry.field(default_factory=list)]

All strawberry.field() options are supported. In particular, default and default_factory also configure the generated dataclass constructor, so User(name="Patrick") in the example above gets a new empty tags list.

On Python 3.11 through 3.13, Strawberry can only read the strawberry.field() options when it can evaluate the annotation when the type is created. When the field type is defined further down the module, or only imported under TYPE_CHECKING , pass the options as the field’s default (account: Account = strawberry.field(...) ), define the type first, or use strawberry.lazy() for it, which works together with field metadata:

from typing import TYPE_CHECKING, Annotated
 
import strawberry
 
if TYPE_CHECKING:
    from .users import User
 
 
@strawberry.type
class Post:
    author: Annotated[
        "User",
        strawberry.lazy(".users"),
        strawberry.field(description="The post author"),
    ]

Otherwise Strawberry raises an UnresolvedStrawberryFieldError when the type is created, instead of ignoring options like permissions. Python 3.14 and newer read the options on a direct unresolved reference without strawberry.lazy() .

The field configuration can be combined with other Strawberry metadata. The order of the metadata does not matter:

@strawberry.type
class Query:
    result: Annotated[
        Success | Failure,
        strawberry.union("Result"),
        strawberry.field(description="The operation result"),
    ]

Use only one strawberry.field() for each field. You can alternatively use the equivalent assignment syntax, such as name: str = strawberry.field(description="The displayed name") .

strawberry.field() must be metadata on the field’s outermost Annotated type. Placing it inside a wrapper configures no GraphQL field, so Strawberry raises an error instead of silently ignoring it:

# Incorrect: strawberry.field() describes the list item, not `names`.
names: list[Annotated[str, strawberry.field(description="A name")]]
 
# Correct: strawberry.field() describes `names`.
names: Annotated[list[str], strawberry.field(description="The names")]

API

@strawberry.type(name: str = None, description: str = None)

Creates an object type from a class definition.

name : if set this will be the GraphQL name, otherwise the GraphQL will be generated by camel-casing the name of the class.

description : this is the GraphQL description that will be returned when introspecting the schema or when navigating the schema using GraphiQL.

Edit this page on GitHub