mrkeyoor.com_
Sun 20 Sept 11:43 UTC
PyPIUtilsupdated 20 Sept 2026

typeguard review

Typeguard checks Python type annotations while code runs. You can validate one value with `check_type()`, decorate a function or class with `@typechecked`, or instrument an entire package through its import hook and pytest plugin. Those checks cover arguments, return values, annotated assignments, and generator traffic; they report mismatches instead of converting data. Version 4.6.0 adds PEP 661 sentinel support, Python 3.15 compatibility, wildcard typing-import detection, and a pytest package-ignore option. It also fixes instrumentation around assignment expressions, Protocol classes, Literal values, and empty tuple annotations, while raising the minimum Python version to 3.10.

Verdict

Typeguard 4.6.0 installed in 0.3 seconds and occupied 1 MB in our sandbox, making it an inexpensive test dependency for checking annotations against real values. Install it for CI and narrow internal contracts; use a parser such as Pydantic when input must be converted or explained to an API caller.

We installed it

Lab card: what happened when we installed typeguardScreenshot of typeguard documentation
Install✓ · 0.3s2 packages on disk · 1 MB
Importimport typeguard in 0.48s · pure Python · py.typed · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does typeguard install cleanly?

Yes. In a fresh container with an empty cache, pip install typeguard finished in 0.3s, leaving 2 packages and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does typeguard need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import typeguard succeeded in 0.48s, and the package ships py.typed for type checkers.

typeguard or beartype: which should you use?

beartype: Choose it when decorator-based runtime checking must stay cheap enough for regular production use. Typeguard 4.6.0 installed in 0.3 seconds and occupied 1 MB in our sandbox, making it an inexpensive test dependency for checking annotations against real values.

When should you not use typeguard?

The boundary needs coercion, defaults, serialization, or a structured list of user-facing errors. Typeguard rejects the value it receives; Pydantic is built for that wider job.

API stability4/5Typeguard 4.6.0 keeps the established `check_type()`, `@typechecked`, import-hook, and pytest entry points while adding package exclusions without replacing those workflows. The caution is interpreter coupling: the instrumenter rewrites Python syntax and this release drops Python 3.9. Teams supporting several interpreter versions should exercise instrumented code on each one, since an unchanged decorator signature does not guarantee identical AST handling.
Docs5/5The stable documentation separates direct checks, decorators, import-hook setup, pytest configuration, collection policies, forward references, suppression, and custom checker lookup. Its version history identifies the exact 4.6.0 fixes for assignment expressions, Protocol classes, Literal ordering, and empty tuples. Readers still need the advanced sections because the quick examples do not surface FIRST_ITEM behavior or every source-rewriting constraint.
Maintenance5/5Release 4.6.0 and the latest repository push both date to 2026-07-26. That release adds Python 3.15 support and closes specific correctness gaps in instrumentation and typing behavior, which is substantive interpreter maintenance. GitHub reports 35 open issues and pull requests and 1,780 stars. The contributor base is concentrated, so interpreter support remains the signal worth watching between upgrades.
Ecosystem4/5The supplied registry snapshot records 17,056,755 weekly downloads. Typeguard plugs into pytest, consumes standard Python annotations, and complements static checkers by observing values that exist only at runtime. It also sits beside mature alternatives with different jobs: Pydantic parses boundary data, attrs owns class-field validation, and beartype targets low-overhead decorator checks. Import-hook instrumentation is useful, though it cannot suit every loader or packaging system.

Use it if

  • A test suite needs to catch runtime values that passed mypy or pyright because they entered through JSON, plugins, mocks, or untyped dependencies.
  • You want annotation checks across an internal package during pytest runs without leaving decorators throughout application code.
  • An existing TypedDict, union, Literal, or nested generic should validate one object without introducing a separate data model.
  • A generator contract matters enough to check yielded values and values sent back into it, as well as ordinary arguments and returns.
Skip it if

Setup reality

Our install of typeguard 4.6.0 completed in 0.3 seconds in a fresh Python 3.12 Bookworm container. It left 2 packages using 1 MB on disk, with 1 direct dependency. The distribution is pure Python, includes py.typed, and requires Python 3.10 or newer. import typeguard completed in 0.48 seconds, and pip-audit found 0 known vulnerabilities. The metadata inspected by our lab did not state a license.

Package-wide checking depends on import order. Install the hook before importing the package you want instrumented; modules already in sys.modules are left alone. The pytest plugin handles that early setup with --typeguard-packages. Version 4.6.0 also accepts --typeguard-packages-ignore, which is useful for generated modules or old code that cannot survive source rewriting. Put @typechecked closest to a function so another decorator does not hide its original body.

Typeguard examines the first item of a collection by default. That keeps a large list[int] check bounded, but a bad value at index 20 can pass unnoticed. Set CollectionCheckStrategy.ALL_ITEMS where complete traversal matters, then measure the cost with real inputs. Direct check_type() calls take their own collection and forward-reference policies; they do not silently inherit every global setting.

A mismatch raises TypeCheckError; it does not turn "7" into 7 or fill a missing field. That makes Typeguard a better fit for tests and internal contracts than request parsing. A warning callback can expose violations during a staged rollout, while CI can treat the warning class as an error. Keep production instrumentation targeted when call frequency or import-hook interaction is uncertain.

Patterns

Check a value against an annotation check-one-value

from typeguard import check_type

ports = check_type([8000, 8001], list[int])
# check_type([8000, "8001"], list[int]) raises TypeCheckError

A passing call returns the same object, while a failing call raises `TypeCheckError`. No string-to-integer conversion occurs.

Apply a TypedDict to decoded JSON check-typed-dict

from typing import TypedDict
from typeguard import check_type

class Job(TypedDict):
    id: int
    queue: str

job = check_type(payload, Job)

The runtime keys and values are checked against `Job`; missing fields and wrong value types are rejected rather than filled or coerced.

Check a function contract instrument-function

from typeguard import typechecked

@typechecked
def reserve(item_id: int, quantity: int) -> bool:
    return inventory.reserve(item_id, quantity)

Keep `@typechecked` closest to the definition. A decorator placed underneath it can prevent Typeguard from seeing the original function source.

Check every supported method on a class instrument-class

from typeguard import typechecked

@typechecked
class Cache:
    def get(self, key: str) -> bytes | None:
        return self._items.get(key)

    def put(self, key: str, value: bytes) -> None:
        self._items[key] = value

Class decoration instruments supported methods in that class. A nested class needs its own decorator.

Instrument a package before import install-import-hook

from typeguard import install_import_hook

manager = install_import_hook(
    packages=["billing"],
    ignore_packages=["billing.generated"],
)
import billing.jobs

# later, if needed
manager.uninstall()

The hook changes only modules imported after installation. Anything already present in `sys.modules` is not revisited.

Enable checks from pytest instrument-pytest-package

pytest --typeguard-packages=billing \
+  --typeguard-packages-ignore=billing.generated

Typeguard 4.6.0 adds `--typeguard-packages-ignore`. The pytest plugin installs its hook early enough to instrument the selected package.

Traverse every collection item check-all-items

from typeguard import CollectionCheckStrategy, typechecked

@typechecked(
    collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS
)
def total(values: list[int]) -> int:
    return sum(values)

FIRST_ITEM is the default. ALL_ITEMS can find a bad later element, and its work increases with collection length.

Set the instrumentation policy once set-global-policy

from typeguard import CollectionCheckStrategy, config

config.collection_check_strategy = CollectionCheckStrategy.ALL_ITEMS

Global configuration affects decorator and import-hook instrumentation. Pass options directly to `check_type()` when a one-off check needs a different policy.

Report mismatches as warnings warn-on-mismatch

from typeguard import config, warn_on_error

config.typecheck_fail_callback = warn_on_error

The callback emits `TypeCheckWarning` instead of raising immediately. Configure the test runner to promote that warning when CI must fail.

Translate a failed boundary check catch-type-error

from typeguard import TypeCheckError, check_type

try:
    settings = check_type(raw_settings, Settings)
except TypeCheckError as exc:
    raise ConfigError(f"invalid settings: {exc}") from exc

Catch `TypeCheckError` specifically so parser, I/O, and application exceptions keep their original meaning.

Pause checks around trusted bulk work suppress-known-work

from typeguard import suppress_type_checks

with suppress_type_checks():
    for record in trusted_snapshot:
        ingest(record)

Suppression covers calls made inside the context, including instrumented callees. Keep its scope narrow so unrelated checks are not hidden.

Check values yielded by a generator check-generator-contract

from collections.abc import Iterator
from typeguard import typechecked

@typechecked
def page_ids() -> Iterator[int]:
    for row in fetch_pages():
        yield row["id"]

Each yielded value is checked when iteration reaches it. A mismatch may therefore appear after the generator was created.

Alternatives

PackageRegistryPick it when
beartypePyPIChoose it when decorator-based runtime checking must stay cheap enough for regular production use.
pydanticPyPIChoose it for external payloads that need parsing, coercion, defaults, serialization, and structured validation errors.
attrsPyPIChoose it when explicit validators belong on declared class fields instead of being inferred across every annotation.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.