Python Type Hints - How to Narrow Types with TypeGuard2021-06-09
I previously covered type narrowing using
In today’s post we’ll cover
TypeGuard, a new special type that allows us to create custom type narrowing functions.
TypeGuard was defined in PEP 647, and is available on Python 3.10+, or on older versions from
Guido van Rossum added support to Mypy in version 0.900, which was released yesterday.
Recall that type narrowing uses particular expressions to infer that, in a given block, a variable has a more limited type than its definition.
For example, using
Type checkers, including Mypy, support a limited number of expressions, such as
But the number of potentially type-narrowing expressions is infinite, especially for parameterized types such as containers.
TypeGuard allows us to write type any expression and communicate to our type checker that it narrows types.
A type narrowing function is one that accepts at least one argument and returns a
Instead of marking the return type as
bool, we use
True means the first argument has type
False means it does not.
Take this example, adapted from the PEP:
True if the given list contains only strings.
We tell Mypy this can narrow the type of
list[str] with the
TypeGuard return type.
Running Mypy on this file, we see this output from the
The second note shows us that within the
if block, Mypy knows
x must be a list of strings.
This allows us to use the list items as
strs there without any errors.
TypeGuard is flexible as it allows us to write arbitrary code to narrow expressions.
It does force us to move even short expressions into separate functions, but that can often a good thing for our code’s readability.
Because there are infinite possible expressions, type checkers cannot validate that our expressions line up with the guarded types.
So we need to write our
TypeGuard functions with care, and test them thoroughly.
PEP 647 also shows generic
TypeGuard functions with
TypeVar, but when I tried out the examples, I found Mypy 0.901 does not yet support them.
There are a few open issues for
TypeGuard so it seems Mypy could use our contributions here!
May your types be well guarded,
Want better tests? Check out my book Speed Up Your Django Tests which teaches you to write faster, more accurate tests.
One summary email a week, no spam, I pinky promise.
- Python Type Hints - How to Narrow Types with isinstance(), assert, and Literal
- Python Type Hints - How to Specify a Class Rather Than an Instance Thereof
Tags: mypy, python
© 2021 All rights reserved.