Features
What does Typeguard check?
The following type checks are implemented in Typeguard:
Types of arguments passed to instrumented functions
Types of values returned from instrumented functions
Types of values yielded from instrumented generator functions
Types of values sent to instrumented generator functions
Types of values assigned to local variables within instrumented functions
What does Typeguard NOT check?
The following type checks are not yet supported in Typeguard:
Types of values assigned to class or instance variables
Types of values assigned to global or nonlocal variables
Stubs defined with
@overload
(the implementation is checked if instrumented)yield from
statements in generator functionsParamSpec
andConcatenate
are currently ignoredTypes where they are shadowed by arguments with the same name (e.g.
def foo(x: type, type: str): ...
)
Other limitations
Local references to nested classes
Forward references from methods pointing to non-local nested classes cannot currently be resolved:
class Outer:
class Inner:
pass
# Cannot be resolved as the name is no longer available
def method(self) -> "Inner":
return Outer.Inner()
This shortcoming may be resolved in a future release.
Using @typechecked
on top of other decorators
As @typechecked
works by recompiling the target function with
instrumentation added, it needs to replace all the references to the original function
with the new one. This could be impossible when it’s placed on top of another decorator
that wraps the original function. It has no way of telling that other decorator that the
target function should be switched to a new one. To work around this limitation, either
place @typechecked
at the bottom of the decorator stack, or use
the import hook instead.
Protocol checking
As of version 4.3.0, Typeguard can check instances and classes against Protocols,
regardless of whether they were annotated with
@runtime_checkable
.
The only current limitation is that argument annotations are not checked for compatibility, however this should be covered by static type checkers pretty well.
Special considerations for if TYPE_CHECKING:
Both the import hook and @typechecked
avoid checking against
anything imported in a module-level if TYPE_CHECKING:
(or
if typing.TYPE_CHECKING:
) block, since those types will not be available at run
time. Therefore, no errors or warnings are emitted for such annotations, even when they
would normally not be found.
Support for generator functions
For generator functions, the checks applied depend on the function’s return annotation. For example, the following function gets its yield, send and return values type checked:
from collections.abc import Generator
def my_generator() -> Generator[int, str, bool]:
a = yield 6
return True
In contrast, the following generator function only gets its yield value checked:
from collections.abc import Iterator
def my_generator() -> Iterator[int]:
a = yield 6
return True
Asynchronous generators work just the same way, except they don’t support returning
values other than None
, so the annotation only has two items:
from collections.abc import AsyncGenerator
async def my_generator() -> AsyncGenerator[int, str]:
a = yield 6
Overall, the following type annotations will work for generator function type checking:
Support for PEP 604 unions on Pythons older than 3.10
The PEP 604 X | Y
notation was introduced in Python 3.10, but it can be used with
older Python versions in modules where from __future__ import annotations
is
present. Typeguard contains a special parser that lets it convert these to older
Union
annotations internally.
Support for generic built-in collection types on Pythons older than 3.9
The built-in collection types (list
, tuple
, dict
,
set
and frozenset
) gained support for generics in Python 3.9.
For earlier Python versions, Typeguard provides a way to work with such annotations by
substituting them with the equivalent typing
types. The only requirement for this
to work is the use of from __future__ import annotations
in all such modules.
Support for mock objects
Typeguard handles the unittest.mock.Mock
class (and its subclasses) specially,
bypassing any type checks when encountering instances of these classes. Note that any
“spec” class passed to the mock object is currently not respected.
Supported standard library annotations
The following types from the standard library have specialized support:
Type(s) |
Notes |
---|---|
|
Any type passes type checks against this annotation. Inheriting from |
|
Original annotation is unwrapped and typechecked normally |
|
Specialized instance checks are performed |
typing.Callable |
Argument count is checked but types are not (yet) |
Keys and values are typechecked |
|
Specialized instance checks are performed |
|
Contents are typechecked |
|
|
|
|
Checked as |
Keys and values are typechecked |
|
Field values are typechecked |
|
typing.Never typing.NoReturn |
Supported in argument and return type annotations |
Run-time protocols are checked with |
|
|
|
Contents are typechecked |
|
Contents are typechecked |
|
Specialized instance checks are performed |
|
typing.Tuple |
Contents are typechecked |
|
Checked as |
Contents are typechecked; On Python 3.8 and earlier, |
|
Constraints and bound types are typechecked |
|
|
PEP 604 unions are supported on all Python versions when
|