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 functions

  • ParamSpec and Concatenate are currently ignored

  • Types 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:

    # 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.

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:




Any type passes type checks against this annotation. Inheriting from Any (typing.Any on Python 3.11+, or typing.extensions.Any) will pass any type check


Original annotation is unwrapped and typechecked normally


Specialized instance checks are performed


Argument count is checked but types are not (yet)

Keys and values are typechecked


Specialized instance checks are performed

Contents are typechecked



Checked as str

Keys and values are typechecked


Field values are typechecked


Supported in argument and return type annotations


Run-time protocols are checked with isinstance(), others are ignored


Contents are typechecked

Contents are typechecked


Specialized instance checks are performed


Contents are typechecked


Checked as bool


Contents are typechecked; On Python 3.8 and earlier, total from superclasses is not respected (see #101 for more information); On Python 3.9.0, false positives can happen when constructing typing.TypedDict classes using old-style syntax (see issue 42059)


Constraints and bound types are typechecked


PEP 604 unions are supported on all Python versions when from __future__ import annotations is used