Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

typing.Annotated is a type hint construct introduced in PEP 593 that enables the attachment of arbitrary, runtime-accessible metadata to a valid Python type. It acts as a structural bridge between static type checking and runtime introspection, allowing developers to decorate types with context-specific objects without altering the underlying static type semantics.

Syntax

The syntax requires exactly two or more arguments: the base type, followed by one or more metadata elements.
from typing import Annotated


# Annotated[BaseType, Metadata1, Metadata2, ...]
  • BaseType: Any valid Python type or type hint (e.g., int, str, List[str]).
  • Metadata: Any valid Python object (e.g., strings, dictionaries, class instances, functions). Python does not evaluate or restrict the types of the metadata arguments.

Static Type Checker Behavior

Static type checkers (such as mypy or pyright) are instructed to completely ignore the metadata arguments. When a type checker encounters Annotated[T, x], it treats it strictly as T.
from typing import Annotated


# To a static type checker, 'age' is simply an 'int'
age: Annotated[int, "Value must be positive"] = 25

Runtime Mechanics and Introspection

At runtime, Annotated does not affect the behavior of the variable or function it annotates. Instead, it instantiates a generic alias object that stores the base type and the metadata. This data is preserved in the __annotations__ dictionary and can be extracted programmatically. To safely introspect Annotated types, use typing.get_type_hints() with the include_extras=True parameter. If include_extras is omitted or set to False, the function strips the Annotated wrapper and returns only the base type.
from typing import Annotated, get_type_hints

def process_data(payload: Annotated[dict, "JSON", {"timeout": 30}]) -> None:
    pass


# Extracting annotations with metadata preserved
hints = get_type_hints(process_data, include_extras=True)
annotated_type = hints['payload']


# Accessing the base type
print(annotated_type.__origin__)  

# Output: <class 'dict'>


# Accessing the metadata tuple
print(annotated_type.__metadata__) 

# Output: ('JSON', {'timeout': 30})

Structural Rules

1. Flattening of Nested Annotations If Annotated types are nested, Python automatically flattens the metadata into a single, one-dimensional tuple. The order of metadata is preserved, starting from the innermost annotation to the outermost.
from typing import Annotated

TypeA = Annotated[int, "Meta1"]
TypeB = Annotated[TypeA, "Meta2"]


# TypeB is evaluated at runtime as:

# Annotated[int, "Meta1", "Meta2"]
2. Type Aliasing Annotated constructs can be assigned to variables to create reusable type aliases. The metadata is bound to the alias and propagates wherever the alias is used.
from typing import Annotated

BoundedInt = Annotated[int, {"min": 0, "max": 100}]

def set_percentage(val: BoundedInt) -> None:
    pass
3. Immutability The __metadata__ attribute exposed on the Annotated alias is an immutable tuple. Once the Annotated type is defined, the metadata sequence cannot be modified at runtime.
Master Python with Deep Grasping Methodology!Learn More