annotated-types

Reusable constraint metadata objects for use with Python's typing.Annotated

Library
PyPI
v0.8.0
615 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
58 /100 Fair
Development Activity 56
Maintenance 28
Community 52
Maturity 56
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
78 /100 Good
Architecture 75
Code Quality 82
Innovation 70
Learning Curve 85

annotated-types provides a small set of standardized metadata objects — Gt, Ge, Lt, Le, Interval, MultipleOf, MinLen, MaxLen, Len, Timezone, Predicate, and Doc — designed to be attached to types via PEP 593’s typing.Annotated. Rather than every validation library inventing its own constraint vocabulary, annotated-types gives them a shared, statically-inspectable representation that tools, IDEs, and runtime validators can all agree on.

It underpins constraint handling in Pydantic v2 and is recognized by FastAPI, msgspec, and other typing-aware libraries, making it a foundational piece of the modern Python typing ecosystem rather than a library developers typically import directly for standalone use.

What You Get

  • Comparison constraints: Gt, Ge, Lt, Le, and a combined Interval type
  • Collection/string constraints: MinLen, MaxLen, and Len
  • MultipleOf for numeric divisibility constraints
  • Timezone constraint for datetime/time annotations
  • Predicate and GroupedMetadata for arbitrary runtime checks and downstream composition
  • Prebuilt generic aliases like LowerCase, IsFinite, and IsDigit for common patterns

Common Use Cases

  • Declaring field-level constraints consumed by Pydantic v2 models via Annotated types
  • Building a custom validation library that needs to interoperate with the broader typing ecosystem
  • Adding static, tool-inspectable documentation and constraints to function signatures
  • Writing framework-agnostic type aliases (e.g. a shared ‘PositiveInt’) that multiple validators can consume identically

Under The Hood

Architecture: The entire implementation lives in a single module, annotated_types/__init__.py (~400 lines), defining frozen dataclasses for each constraint (Gt, Ge, Lt, Le, Interval, MultipleOf, MinLen, MaxLen, Len, Timezone, Predicate, Not, Doc) plus a GroupedMetadata protocol that downstream libraries implement to expose composite constraint bundles that iterate into individual metadata objects. There is no runtime enforcement logic at all — the package is purely descriptive metadata meant to be interpreted by consuming validators.

Tech Stack: Pure Python with zero runtime dependencies, using dataclasses and typing_extensions/typing for structural types, targeting Python 3.10 through 3.14. Packaging uses a standard pyproject.toml with Hatchling-style metadata and a Makefile for local dev tasks.

Code Quality: Tests are split between tests/ (test_main.py, test_grouped_metadata.py) and an in-package annotated_types/test_cases.py that other libraries can import and reuse to verify their own interpretation of these metadata types against a shared conformance suite — an unusually thoughtful design for an ecosystem-spec package. Type hints are exhaustive and the codebase is fully typed (Typing :: Typed classifier), with CI running across all supported Python versions per pyproject classifiers.

API Design: The API is deliberately minimal — plain dataclass constructors (Gt(0), Len(1, 10)) with obvious, self-documenting names and no configuration ceremony, designed to be composed inside Annotated[T, ...] with zero learning curve for anyone already familiar with PEP 593. Prebuilt generic aliases (LowerCase, IsFinite, IsDigit) further reduce boilerplate for common cases, and the README doubles as a de facto specification document for implementers.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers