Type hints

Type hints are a modern feature of Python available since 3.5 whose existence is heavily influenced by the features of type-safe languages such as Rust. To learn more about type hints in Python, see Real Python’s Type hinting walkthrough .

When using Strawberry to build graphQL APIs, as was shown in Schema basics , type hints are required within classes decorated by @strawberry.type & @strawberry.input and functions decorated by @strawberry.field & strawberry.mutation . These type hints are sourced as the keywords str , int , float , and from packages imported directly from the Python standard libraries typing , that has been available since Python 3.5, datetime , and decimal .

Mapping to graphQL types

The complete mapping of the required type hints for the relevant graphQL types is as follows:

GraphQL Python
ID strawberry.ID
String str
Integer int
Float float
Decimal decimal.Decimal
Array , [] typing.List or list
Union typing.Union or |
Nullable typing.Optional or None |
Date datetime.date
Datetime datetime.datetime
Time datetime.time

where typing , datetime , and decimal are all part of the Python standard library. There is also typing.Dict that possesses no mapping since it is the entire structure of the graphQL query itself that is a dictionary.

There are a few different ways in which these Python type hints can be used to express the required Strawberry graphQL type annotation.

Example

A complete example of this, extending upon Schema basics , might be the following:

import datetime
import decimal
from typing import List, Optional
 
import strawberry
 
BOOKS_LOOKUP = {
    "Frank Herbert": [
        {
            "title": "Dune",
            "date_published": "1965-08-01",
            "price": "5.99",
            "isbn": 9780801950773,
        }
    ],
}
 
 
@strawberry.type
class Book:
    title: str
    author: "Author"
    date_published: datetime.date
    price: decimal.Decimal
    isbn: str
 
 
def get_books_by_author(root: "Author") -> List["Book"]:
    stored_books = BOOKS_LOOKUP[root.name]
 
    return [
        Book(
            title=book.get("title"),
            author=root,
            date_published=book.get("date_published"),
            price=book.get("price"),
            isbn=book.get("isbn"),
        )
        for book in stored_books
    ]
 
 
@strawberry.type
class Author:
    name: str
    books: List[Book] = strawberry.field(resolver=get_books_by_author)
 
 
@strawberry.type
class Group:
    name: Optional[str]  # groups of authors don't necessarily have names
    authors: List[Author]
 
    @strawberry.field
    def books(self) -> List[Book]:
        books = []
 
        for author in self.authors:
            books += get_books_by_author(author)
 
        return books

Motivation

Python, much like Javascript and Ruby, is a dynamically typed language that allows for high-level programming where the fundamental types of variables, e.g. integers, arrays, hash-maps, etc., are understood by the machine at runtime through Just-in-Time compilation.

Yet, much like the low-level languages of C, Java, and Rust, the graphQL query language is statically typed since the data types defined by the schema must be known prior to compiling the API code in order to define a definite schema to query against.

In the low-level statically typed languages mentioned above, every function must have the types of both their arguments and returns explicitly declared so that the compiler can interpret their behaviours correctly and ensure type safety and consistency.

Strawberry takes inspiration from these languages by requiring that all of its types, fields, resolvers, and mutations declare the types of their arguments and returns. Through this, the schema is generated in a standard and efficient way that aligns with the style-direction of Python and programming as a whole.

Edit this page on GitHub