PEP: 835
Title: Shorthand syntax for Annotated type metadata
Author: Till Varoquaux <till.varoquaux@gmail.com>
Sponsor: Ivan Levkivskyi <levkivskyi@gmail.com>
Discussions-To: https://discuss.python.org/t/pep-835-shorthand-syntax-for-annotated-type-metadata/107814
Status: Draft
Type: Standards Track
Topic: Typing
Created: 12-Jun-2026
Python-Version: 3.16
Post-History: `19-Apr-2026 <https://discuss.python.org/t/shorthand-syntax-for-annotated-type-metadata/106888>`__,
              `18-Jun-2026 <https://discuss.python.org/t/pep-835-shorthand-syntax-for-annotated-type-metadata/107814>`__,

Abstract
========

This PEP proposes overloading the ``@`` operator on types to allow writing
``Annotated[T, M]`` as ``T @M``.

Motivation
==========

:pep:`593` (``Annotated``) has seen widespread adoption. Major frameworks
(FastAPI, Pydantic, SQLAlchemy, msgspec, Typer, beartype) now rely on it as the
standard type metadata mechanism [1]_.

However, its verbosity remains a barrier to adoption:

1. **Libraries invent aliases to hide it.** Frameworks routinely create DSLs or
   type aliases (e.g., ``PositiveInt``) to shield users from ``Annotated[...,
   ...]`` boilerplate [2]_.
2. **Major projects defer adoption.** PyTorch [3]_, TorchTyping, and Beartype
   [4]_ deferred adopting ``Annotated`` for tensor shapes, explicitly citing
   its verbose syntax and waiting for a native language solution.
3. **It impacts readability.** During the :pep:`727` discussions, participants
   warned that relying on ``Annotated`` for everyday documentation would make
   code unreadable, contributing to the PEP's withdrawal [5]_.

A container-like syntax opposes Python's evolution. Python is actively replacing
generic wrappers like ``typing.Union`` with operators like ``|`` (and the
proposed ``&`` for intersections), evolving type annotations into an arithmetic
of types.

The ``@`` shorthand aligns syntax with semantics. By applying type metadata as a
postfix operator, it:

- **Reduces nesting** (no brackets required).
- **Reduces tokens** (no ``typing.Annotated`` import).
- **Improves locality** (the base type remains front-and-center).
- **Extends the arithmetic of types** (type metadata acts as an operation on an
  existing type expression rather than a generic container).

This resolves the conflict between concise syntax and strict typing::

    class User(BaseModel):
        # Bad: Early frameworks abused defaults, breaking static analysis
        id: int = Field(gt=0)

        # Verbose: PEP 593 fixed semantics, but hindered adoption
        id: Annotated[int, Field(gt=0)]

        # Proposed: Concise while preserving PEP 593 semantics
        id: int @Field(gt=0)

As an operator, ``@`` composes natively::

    # Inside generics
    list[Annotated[str, Field(max_length=50)]]
    list[str @Field(max_length=50)]

    # Within a union
    Annotated[int, Ge(0)] | Annotated[str, Len(5)]
    int @Ge(0) | str @Len(5)

    # Across an entire union
    Annotated[str | None, Field(description="Optional string")]
    (str | None) @Field(description="Optional string")

    # Within callables
    Callable[[Annotated[int, Ge(0)]], str]
    Callable[[int @Ge(0)], str]

Historical Context and Prior Art
--------------------------------

When the community debated alternatives in late 2023 [6]_ and 2025 [7]_,
discussion trended toward the ``@`` operator because it visually aligns with
existing Python `decorators
<https://docs.python.org/3/glossary.html#term-decorator>`__.

Adopting ``@`` for type metadata also follows the precedent of repurposing runtime
operators for static typing, as seen with ``[]`` for generics (:pep:`585`) and
``|`` for unions (:pep:`604`) [8]_.

The postfix syntax mirrors features in other statically typed languages:

- **C++:** Uses ``[[attribute]]`` for types (e.g., ``[[nodiscard]] int f();``).
- **Java / Kotlin:** Uses ``@Annotation`` (e.g., ``List<@NonNull String>`` or
  ``val x: @NotNull String``).
- **OCaml:** Uses ``[@attribute]`` postfix syntax (e.g.,
  ``type t = int [@default 0]``).

Terminology
===========

To clarify discussion around annotations and metadata, the following terms
apply:

- **Type expression**: e.g., ``x: <this>``. An expression within a type hint
  that evaluates to a valid type, as specified in the `Typing Specification
  <https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions>`__
  (:pep:`484`).
- **Type metadata**: e.g., ``int @<this>``. Data attached to a type expression
  via ``Annotated`` (:pep:`593`, :pep:`746`).
- **Non-typing annotation**: e.g., `@no_type_check
  <https://docs.python.org/3/library/typing.html#typing.no_type_check>`__
  wrapping ``x: <this>``. Annotations that are not intended to be evaluated as
  type expressions (e.g.: ignored by type checkers).
- **Symbol decorator**: Applying metadata directly to a variable or field
  declaration, rather than to its underlying type. This distinction is
  well-established in languages like Java:

  .. code-block:: java

      class Application {
          // Field Decorator (symbol decorator)
          @Inject
          private Service s;

          // Type Decorator (type metadata)
          private @NonNull String name;
      }

- **Symbol metadata** (or **field metadata**): Metadata attached to a
  symbol. It is distinct from type metadata, as it applies to the specific
  instance of the variable rather than the type itself.

Specification
=============

The proposed syntax uses the ``__matmul__`` operator to attach metadata to a
type::

    # Current syntax
    x: Annotated[int, Range(0, 10)]

    # Proposed shorthand
    x: int @Range(0, 10)

Operator Precedence
-------------------

Because ``@`` binds tighter than the ``|`` union operator (:pep:`604`), distinct
constraints can be attached directly to specific types within a union without
parentheses. For example, a US zip code might be a 5-digit integer *or* a
5-character string::

    zip_code: int @Ge(10000) @Le(99999) | str @Len(5)

To attach metadata to the entire union, use parentheses::

    # Attaches only to 'str'
    int | str @Metadata    # equivalent to: int | Annotated[str, Metadata]

    # Attaches to the entire union
    (int | str) @Metadata  # equivalent to: Annotated[int | str, Metadata]



Flattening Multiple Metadata
----------------------------

Chained metadata flattens the resulting ``Annotated`` object.  ``T @m1 @m2``
evaluates to ``Annotated[T, m1, m2]``, never
``Annotated[Annotated[T, m1], m2]``. This mirrors ``typing.Annotated``'s
existing runtime behavior.

This same logic applies when the left-hand operand is an existing ``Annotated``
type::

    Annotated[int, m1] @m2  # AnnotatedType(int, m1, m2) (flattened)

Runtime Behavior
----------------

``@`` produces a ``types.AnnotatedType`` (a new built-in C type). The existing
``typing.Annotated`` unifies with this type. ``typing.Annotated[X, Y]`` and ``X
@Y`` return the exact same object:

.. code-block:: pycon

    >>> type(int @Field()) is type(Annotated[int, Field()])
    True
    >>> typing.Annotated is types.AnnotatedType
    True

An ``AnnotatedType`` object exposes the following attributes:

- ``__origin__``: The base type (e.g., ``int``).
- ``__metadata__``: A tuple of metadata items.
- ``__args__``: The tuple ``(origin, *metadata)``, for compatibility with
  ``typing.get_args()``.
- ``__parameters__``: A tuple of unique free type parameters of the type.

The ``repr()`` of an ``AnnotatedType`` uses the shorthand syntax:

.. code-block:: pycon

    >>> int @Field(gt=0)
    int @Field(gt=0)

Handling of ``None``
--------------------

``NoneType`` explicitly avoids implementing ``__matmul__`` to prevent masking
runtime bugs.

For example, a developer might forget to check for ``None`` before matrix
multiplication:

.. code-block::
   :class: bad

    def matmul_arrays(a: np.array | None, b: np.array):
        return a @ b  # oops, forgot to check for None

If ``NoneType.__matmul__`` existed, this would silently return an
``AnnotatedType`` instead of raising a ``TypeError``.

``annotationlib.Format.TYPE`` sidesteps this limitation in typing
expressions. It evaluates structurally, correctly parsing ``None @Metadata``
into an ``AnnotatedType``. Outside of type expressions, use ``Annotated[None,
Metadata]``.

Supported Left-Hand Operands
-----------------------------

The ``@`` operator adds ``nb_matrix_multiply`` to ``type`` and to all typing
constructs that support the ``|`` union operator (``types.GenericAlias``,
``types.UnionType``, ``types.AnnotatedType``, ``typing.TypeVar``,
``typing.ParamSpec``, ``typing.TypeVarTuple``, ``typing.TypeAliasType``,
``typing.ForwardRef``, and ``sentinel`` objects).

Applying ``@`` to a class evaluates as type metadata; applying it to an instance
performs arithmetic.

For example, ``int @Field()`` produces an ``AnnotatedType``, while ``42 @
something`` raises a ``TypeError`` (or delegates to ``__rmatmul__``).

Likewise, ``ndarray @Field()`` produces an ``AnnotatedType``, even though
``ndarray`` instances define ``__matmul__`` for matrix multiplication.

Custom metaclasses can overload ``__matmul__`` provided ``@`` is avoided in type
expressions.

Forward References and Deferred Evaluation
-------------------------------------------

Under :pep:`749`'s lazy evaluation, existing ``annotationlib`` formats do not
preserve the structure of ``@`` expressions when names are unresolvable.
``Format.FORWARDREF`` stringifies unresolvable names::

    class Model:
        ref: NotYetDefined @Field(gt=0)

This produces an opaque ``ForwardRef('"NotYetDefined" @Field(gt=0)')``. The
metadata is enclosed within the string, preventing libraries from easily
inspecting it.

``Format.TYPE`` assumes typing semantics and evaluates type expressions
structurally:

* **Unresolvable Names:** Unresolvable names are wrapped in a ``ForwardRef``
  independently, leaving operators intact.
* **Union Types:** The ``|`` operator evaluates to ``types.UnionType``.
* **Annotated Types:** The ``@`` operator evaluates to ``types.AnnotatedType``.
* **Metadata Boundary:** Structural evaluation applies only to the type space.
  Expressions within the metadata (the right-hand side of ``@`` or the
  subsequent arguments of ``Annotated``) are evaluated as values. Unresolvable
  expressions there produce a single opaque ``ForwardRef`` (identical to
  ``Format.FORWARDREF``).

For example, the ``NotYetDefined @Field(gt=0)`` annotation evaluates into an
``AnnotatedType`` where the metadata remains immediately accessible::

    AnnotatedType(ForwardRef('NotYetDefined'), Field(gt=0))

This also resolves the pre-existing limitation where ``"Foo" | int`` produced
``ForwardRef('Foo | int')`` under ``Format.FORWARDREF``.

Rationale
=========

``Annotated`` forces type metadata to resemble a parameterized class. A postfix
operator provides identical semantics without nesting.

Reusing the existing ``@`` operator leaves the Python parser unchanged. The
operator's new meaning is isolated to type evaluation, where ``T @M`` lowers to
``Annotated[T, M]``. Type checkers (Mypy, Pyright) also require no parser
changes, handling the syntax directly during semantic analysis. We prototyped a
Ruff conversion rule for automated migrations, and CPython prototype testing
confirms that libraries like ``typer`` and ``pydantic`` continue to work without
modification.

Parentheses and Verbosity
-------------------------

Writing ``address: (str | None) @Field(...)`` adds verbosity due to the lack
of native symbol decorators. Frameworks co-opt ``Annotated`` to configure
fields, even though the developer's intent is to configure the ``address``
field, not the ``str | None`` type. While the ``@`` shorthand cannot fully
eliminate this structural limitation, it significantly reduces the syntactic
weight of the workaround compared to ``Annotated[str | None, Field(...)]``.

Why the @ Operator?
-------------------

Selecting the correct operator for metadata involves balancing three
considerations:

1. **Precedence:** Binding tighter than ``|`` (Union) and ``&`` (proposed
   Intersection) ensures expressions like ``int @Field() | str`` parse correctly
   unparenthesized. This excludes operators like ``|``, ``^``, and ``&``.
2. **Ecosystem Compatibility:** New keywords require ecosystem-wide parser
   migrations. Because Python's type system is evolving into an arithmetic of
   types (e.g., replacing ``Union`` with ``|``), reusing an operator extends
   this pattern without unnecessary churn.
3. **Semantic Clarity:** The chosen syntax should avoid colliding with
   established intuitions for primitive types.

This leaves the set of overridable binary operators that bind tighter than
``&``: ``**``, ``*``, ``@``, ``/``, ``//``, ``%``, ``+``, ``-``, ``>>``, and
``<<``.

Standard arithmetic operators like ``+``, ``-``, ``/``, ``//``, ``*``, ``**``,
and ``%`` are misleading. Reading ``int + x`` or ``float / Field()`` strongly
implies mathematical evaluation, not metadata decoration.

The remaining candidates are ``<<``, ``>>``, and ``@``. We chose ``@`` because
it already associates with metadata in Python via decorators. While libraries
like NumPy use it for matrix multiplication, it isn't as tied to arithmetic as
operators like ``+`` or ``/``.


Backwards Compatibility
=======================

The pure-Python ``typing._AnnotatedAlias`` class is replaced with a native C
implementation (``types.AnnotatedType``). ``typing.Annotated`` becomes a
reference to this C type rather than a special form with a custom metaclass.

To ensure a smooth transition, this legacy class is retained as a deprecated
compatibility shim. Code using ``isinstance(x, typing._AnnotatedAlias)`` will
continue to work but emit a ``DeprecationWarning``. The shim is scheduled for
removal in Python 3.21 (see `Open Issues`_).

Code that should be updated:

- ``type(ann).__name__ == '_AnnotatedAlias'`` → use ``isinstance(ann,
  types.AnnotatedType)`` or ``typing.get_origin(ann) is Annotated``
- ``typing._AnnotatedAlias(origin, metadata)`` → use ``Annotated[origin,
  *metadata]`` or ``origin @m1 @m2``

**Backporting via typing_extensions:** Like ``X | Y``, the ``@`` shorthand
requires changes to the metatype (``type.__matmul__``), which cannot be patched
from pure Python. The shorthand is only available on Python 3.16+. The existing
``Annotated[X, Y]`` syntax continues to work on all supported versions and
should be used when backwards compatibility is required.

Security Implications
=====================

There are no direct security implications.

How to Teach This
=================

In Python, the ``@`` symbol already has an established association with metadata
through decorators. The annotation shorthand extends this intuition to the type
system: ``int @Field(gt=0)`` reads as "``int``, decorated with ``Field(gt=0)``."

For beginners, the key rule is: **in a type annotation, ``@`` means "with this
metadata."** For experienced developers, the mental model maps directly to
standard Python operator precedence (``@`` binds tighter than ``|``).

Documentation and teaching materials should introduce the shorthand as the
primary syntax for applying metadata. The verbose ``typing.Annotated`` form
should be treated as an advanced detail, primarily relevant to library authors
or when dynamically generating types.

**Visual Style:** Format the shorthand as ``type @annot`` (e.g., ``int
@Metadata(...)``), with a space before the ``@`` and no space after it. This
distinguishes it from standard matrix multiplication (``A @ B``) and aligns
visually with function decorators (``@decorator``) and Java annotations. Code
formatters (like Ruff and Black) should enforce this spacing within typing
contexts.

Usage Examples
==============

**Pydantic Validation:** The shorthand can be used in data validation
scenarios::

    from pydantic import BaseModel, Field, HttpUrl
    from annotated_types import Len

    class Project(BaseModel):
        name: str @Field(title="Project Name") @Len(1)
        url: HttpUrl @Field(description="The project homepage")
        stars: int @Field(ge=0) = 0

**FastAPI Dependency Injection:** In FastAPI, the shorthand simplifies complex
parameter definitions::

    from fastapi import FastAPI, Header, Depends

    app = FastAPI()

    @app.get("/secure")
    async def secure_endpoint(token: str @Header(description="Auth token")):
        return {"status": "authorized"}

**SQLModel and Database Definitions:** SQLModel relies on ``Annotated`` to
define column properties. The shorthand syntax cleans up these definitions::

    from sqlmodel import SQLModel, Field

    class Hero(SQLModel, table=True):
        id: (int | None) @Field(primary_key=True) = None
        name: str @Field(index=True)
        secret_name: str
        age: (int | None) @Field(index=True) = None

**Testing and Formal Verification:** Libraries like Hypothesis and CrossHair use
``annotated-types`` to constrain test generation. The shorthand provides a clean
syntax for specifying test boundaries::

    from dataclasses import dataclass
    from annotated_types import Ge, Interval
    from hypothesis import given

    @dataclass
    class InventoryItem:
        # A non-negative quantity
        quantity: int @Ge(0)
        # A price bounded between 1 and 100
        price: float @Interval(gt=0, le=100)

    @given(...)
    def test_inventory(item: InventoryItem):
        assert item.price * item.quantity >= 0

Reference Implementation
========================

Prototype implementations are available for the following tools:

- **CPython:** `CPython at-type-annot
  <https://github.com/till-varoquaux/cpython/compare/main...feature/at-type-annot>`_
- **CPython (with annotation-lib structural forward references):** `CPython
  forward-stringifier
  <https://github.com/till-varoquaux/cpython/compare/feature/at-type-annot...feature/forward-stringifier>`_
- **Mypy:** `Mypy at-type-annot
  <https://github.com/till-varoquaux/mypy/compare/master...feature/at-type-annot>`_
- **Mypyc/ast_serialize:** `ast_serialize at-type-annot
  <https://github.com/till-varoquaux/ast_serialize/compare/main...feature/at-type-annot>`_
- **Pyright:** `Pyright at-type-annot
  <https://github.com/till-varoquaux/pyright/compare/main...feature/at-type-annot>`_
- **Ruff:** `Ruff at-type-annot
  <https://github.com/till-varoquaux/ruff/compare/main...till-varoquaux:ruff:feature/at-type-annot>`_

``builtins.type`` in Typeshed will be updated to include
``def __matmul__(self, other: Any) -> types.AnnotatedType: ...`` to support type
checkers.

Rejected Ideas
==============

Alternative Syntaxes
--------------------

Debates around reusing ``@`` yielded several alternatives:

- A new infix operator: ``int <@ Field(...)``
- A new soft keyword: ``int annotated Interval(1, 10)``
- Bracket syntax: ``x: int {Gt(10), Lt(20)}``

These lacked consensus. The ``@`` symbol also extends cleanly to symbol
decorators if the language pursues that route later.

Reliance on ``__rmatmul__``
---------------------------

We explicitly reject relying on metadata objects implementing ``__rmatmul__``
(e.g., via a base class) to return an ``Annotated`` type::

    class Metadata[T = object]:
        def __rmatmul__(self, typ: TypeForm[T], /) -> TypeForm[T]:
            return Annotated[typ, self]

    class Le(Metadata[int]):
        ...

This approach is rejected for two reasons. First, relying on arbitrary
right-hand objects to implement ``__rmatmul__`` breaks the type expression
model, complicating the assignment of fixed static meanings to operators. This
is inconsistent with how ``|`` works and contradicts the type expression grammar
defined in the specification. Second, :pep:`593` explicitly permits any valid
Python object as metadata (e.g., strings, dicts). Implementing ``__matmul__``
directly on the ``type`` metaclass avoids opt-in base classes and provides
consistent behavior.

Parameter/Field Decorators
--------------------------

True parameter/field decorators were rejected for now. Modifying the core parser
for symbol-level decorators opens a complex design space; this PEP scopes the
``@`` operator to type expressions.

Avoiding @ Due to Matrix Multiplication
---------------------------------------

We rejected the argument that ``@`` should be avoided because of its association
with matrix multiplication. Within a type expression, Python already reuses
standard operators (like ``|`` for unions and ``[]`` for generics) with
typing-specific semantics (see `Why the @ Operator?`_).

Evaluating Type Expressions as Runtime Code
-------------------------------------------

The design explicitly couples ``Format.TYPE`` to type expression semantics,
reinforcing the boundary between static typing and runtime evaluation:

* **Non-Typing Annotations:** Frameworks using custom ``@`` operators in
  annotations remain supported via ``Format.STRING`` and ``Format.VALUE``.  They
  are incompatible with ``Format.TYPE``, which enforces typing semantics.
* **Structural Evaluation:** Because ``Format.TYPE`` handles the ``@`` operator
  structurally, it can evaluate constructs like ``None @Metadata`` even though
  the global ``NoneType`` does not implement ``__matmul__``.

Future Work
===========

Although this proposal stands on its own, establishing ``@`` for type metadata
enables several future extensions.

Native Symbol Decorators
------------------------

Developers request framework-agnostic field decorators::

    class User(BaseModel):
        @Field(primary_key=True)
        id: int

Future proposals will likely need to navigate between two architectural models:

- **The descriptor model:** The decorator acts as a runtime function returning a
  `descriptor <https://docs.python.org/3/howto/descriptor.html>`__, actively
  intercepting attribute access (similar to standard Python function
  decorators).
- **The metadata model:** The field configuration is treated as passive symbol
  metadata, leaving the enclosing class to process it during creation.

This proposal aligns with the metadata model. Type-directed libraries typically
inspect static definitions during class creation rather than relying on
standalone descriptors.

``@Field(...) id: int`` would evaluate identically to ``id: int
@Field(...)``. This allows existing frameworks to inspect field configurations
and continue working unmodified. Under this model, value-space decorators modify
objects at runtime, while type-space decorators attach metadata to a type.

Targeted Metadata
-----------------

Future extensions to :pep:`746` could support annotation targets. By
intersecting a base type with an explicit target constraint, type checkers will
validate *where* metadata is allowed to exist. This mitigates misuse (e.g.,
placing a ``@Column`` on a function parameter rather than a class field):

*(Note: The following example assumes the ``&`` operator for intersection types
has been added.)*

::

    from typing import Target

    class Column:
        """Valid only on integers that are fields of a SQLAlchemy Model."""
        __supports_annotated_base__: int & Target.FIELD[SQLAlchemy.Model]

Establishing a native syntax for metadata provides a structural foundation for
future extensions like annotation targets.

Open Issues
===========

**Deprecation Timeline:** As a private class, ``typing._AnnotatedAlias`` could
bypass the standard 5-year deprecation policy (:pep:`387`). Should we
fast-track its removal?

**annotationlib.Format.TYPE Extraction:** ``Format.TYPE`` improves
type expression evaluation (e.g., properly resolving ``|`` unions). Does this
warrant a standalone PEP?

Acknowledgements
================

Thanks to Hugo van Kemenade, Jelle Zijlstra, and Eric Traut for their feedback,
guidance, and assistance in refining this proposal.

References
==========

- `Discussion on Python Discourse <https://discuss.python.org/t/106888>`_

.. [1] Major frameworks supporting ``Annotated`` include:

   * FastAPI support for ``Annotated``:
     https://fastapi.tiangolo.com/tutorial/query-params-str-validations/

   * Pydantic support for ``Annotated``:
     https://docs.pydantic.dev/latest/concepts/types/#annotated-types

   * cattrs support for ``Annotated``:
     https://cattrs.readthedocs.io/en/latest/validation.html#annotated

   * msgspec support for ``Annotated``:
     https://jcristharif.com/msgspec/supported-types.html#annotated

   * SQLAlchemy 2.0 support for ``Annotated``:
     https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html#using-annotated-declarative-table-type-annotated-forms-for-mapped-column

   * Typer support for ``Annotated``:
     https://typer.tiangolo.com/tutorial/parameter-types/annotated/

   * Beartype support for ``Annotated`` (Validators):
     https://beartype.readthedocs.io/en/latest/api_vale/

.. [2] Examples of users and framework authors citing ``Annotated`` verbosity:

   * *"Annotated syntax is too long: Introduction of Annotated params made
     function params more logical, but on the other hand longer/more verbose"* —
     Vitaliy Kucheryaviy, author of Django Ninja:
     https://github.com/tiangolo/fastapi/discussions/10055#discussion-5507018

   * *"I personally find this solution [using Annotated] a bit tedious when
     you start having a lot of models/fields"* — g0di, Pydantic user:
     https://github.com/pydantic/pydantic/discussions/2419#discussioncomment-7228409

   * SQLAlchemy 2.0 Migration Guide (advocating Annotated aliases to
     mitigate verbosity):
     https://docs.sqlalchemy.org/en/20/changelog/migration_20.html#step-five-make-use-of-pep-593-annotated-to-package-common-directives-into-types

.. [3] *"My main concern here is that Annotated[torch.Tensor, dtype] is quite
   verbose, and seems to go in the opposite direction to where we'd like to end
   up"* — Ralf Gommers, NumPy maintainer:
   https://github.com/pytorch/pytorch/issues/98702#issuecomment-1504794519

.. [4] *"I'm not writing something stupidly verbose like: TensorBatchXChannels
   = Annotated[...]"* — Patrick Kidger, author of TorchTyping:
   https://github.com/beartype/beartype/discussions/96#discussioncomment-2245014

.. [5] *"Functions where the arguments have type annotations can already be
   rather long, and Annotated on its own is rather verbose, so I’m generally
   glad it’s rare"* — Paul Moore on PEP 727:
   https://discuss.python.org/t/32566/17

.. [6] 2023 Python Discourse discussion proposing ``@`` as an alternative to
   Annotated:
   https://discuss.python.org/t/40751

.. [7] 2025 Python Discourse discussion converging on dedicated ``@`` syntax:
   https://discuss.python.org/t/103699

.. [8] *"That by itself doesn’t seem a big objection – type annotations reuse
   all kinds of operations, including x[y] and x | y."* — Guido van Rossum, on
   repurposing the @ operator for typing:
   https://discuss.python.org/t/40751/3

Copyright
=========

This document is placed in the public domain or under the CC0-1.0-Universal
license, whichever is more permissive.
