Python has support for optional "type hints" (also called "type annotations").
These "type hints" or annotations are a special syntax that allow declaring the type of a variable.
By declaring types for your variables, editors and tools can give you better support.
This is just a quick tutorial / refresher about Python type hints. It covers only the minimum necessary to use them with FastAPI... which is actually very little.
FastAPI is all based on these type hints, they give it many advantages and benefits.
But even if you never use FastAPI, you would benefit from learning a bit about them.
Note
If you are a Python expert, and you already know everything about type hints, skip to the next chapter.
The syntax using typing is compatible with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc.
As Python advances, newer versions come with improved support for these type annotations and in many cases you won't even need to import and use the typing module to declare the type annotations.
If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity.
In all the docs there are examples compatible with each version of Python (when there's a difference).
For example "Python 3.6+" means it's compatible with Python 3.6 or above (including 3.7, 3.8, 3.9, 3.10, etc). And "Python 3.9+" means it's compatible with Python 3.9 or above (including 3.10, etc).
If you can use the latest versions of Python, use the examples for the latest version, those will have the best and simplest syntax, for example, "Python 3.10+".
You can declare that a variable can be any of several types, for example, an int or a str.
In Python 3.6 and above (including Python 3.10) you can use the Union type from typing and put inside the square brackets the possible types to accept.
In Python 3.10 there's also a new syntax where you can put the possible types separated by a vertical bar (|).
Using Optional[str] instead of just str will let the editor help you detecting errors where you could be assuming that a value is always a str, when it could actually be None too.
Optional[Something] is actually a shortcut for Union[Something, None], they are equivalent.
This also means that in Python 3.10, you can use Something | None:
If you are using a Python version below 3.10, here's a tip from my very subjective point of view:
🚨 Avoid using Optional[SomeType]
Instead ✨ use Union[SomeType, None] ✨.
Both are equivalent and underneath they are the same, but I would recommend Union instead of Optional because the word "optional" would seem to imply that the value is optional, and it actually means "it can be None", even if it's not optional and is still required.
I think Union[SomeType, None] is more explicit about what it means.
It's just about the words and names. But those words can affect how you and your teammates think about the code.
These types that take type parameters in square brackets are called Generic types or Generics, for example:
You can use the same builtin types as generics (with square brackets and types inside):
list
tuple
set
dict
And the same as with Python 3.8, from the typing module:
Union
Optional (the same as with Python 3.8)
...and others.
In Python 3.10, as an alternative to using the generics Union and Optional, you can use the vertical bar (|) to declare unions of types, that's a lot better and simpler.
You can use the same builtin types as generics (with square brackets and types inside):
list
tuple
set
dict
And the same as with Python 3.8, from the typing module:
Pydantic is a Python library to perform data validation.
You declare the "shape" of the data as classes with attributes.
And each attribute has a type.
Then you create an instance of that class with some values and it will validate the values, convert them to the appropriate type (if that's the case) and give you an object with all the data.
And you get all the editor support with that resulting object.
Pydantic has a special behavior when you use Optional or Union[Something, None] without a default value, you can read more about it in the Pydantic docs about Required Optional fields.
Python also has a feature that allows putting additional metadata in these type hints using Annotated.
In Python 3.9, Annotated is part of the standard library, so you can import it from typing.
fromtypingimportAnnotateddefsay_hello(name:Annotated[str,"this is just metadata"])->str:returnf"Hello {name}"
In versions below Python 3.9, you import Annotated from typing_extensions.
It will already be installed with FastAPI.
fromtyping_extensionsimportAnnotateddefsay_hello(name:Annotated[str,"this is just metadata"])->str:returnf"Hello {name}"
Python itself doesn't do anything with this Annotated. And for editors and other tools, the type is still str.
But you can use this space in Annotated to provide FastAPI with additional metadata about how you want your application to behave.
The important thing to remember is that the first type parameter you pass to Annotated is the actual type. The rest, is just metadata for other tools.
For now, you just need to know that Annotated exists, and that it's standard Python. 😎
Later you will see how powerful it can be.
Tip
The fact that this is standard Python means that you will still get the best possible developer experience in your editor, with the tools you use to analyze and refactor your code, etc. ✨
And also that your code will be very compatible with many other Python tools and libraries. 🚀
FastAPI takes advantage of these type hints to do several things.
With FastAPI you declare parameters with type hints and you get:
Editor support.
Type checks.
...and FastAPI uses the same declarations to:
Define requirements: from request path parameters, query parameters, headers, bodies, dependencies, etc.
Convert data: from the request to the required type.
Validate data: coming from each request:
Generating automatic errors returned to the client when the data is invalid.
Document the API using OpenAPI:
which is then used by the automatic interactive documentation user interfaces.
This might all sound abstract. Don't worry. You'll see all this in action in the Tutorial - User Guide.
The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), FastAPI will do a lot of the work for you.
Info
If you already went through all the tutorial and came back to see more about types, a good resource is the "cheat sheet" from mypy.