.. Comment: this file is automatically generated by `update_example_docs.py`.
   It should not be modified manually.

.. _example-category-generics:

Generics
========

:mod:`tyro`'s understanding of Python's type system includes user-defined
parameterized types, which can reduce boilerplate and improve type safety.


.. _example-01_generics_py312:

Generics (3.12+)
----------------

This example uses syntax introduced in Python 3.12 (`PEP 695 <https://peps.python.org/pep-0695/>`_).

.. note::

    If used in conjunction with :code:`from __future__ import annotations`, the updated type parameter syntax requires Python 3.12.4 or newer. For technical details, see `this CPython PR <https://github.com/python/cpython/pull/118009>`_.


.. code-block:: python
    :linenos:

    # 01_generics_py312.py
    import dataclasses

    import tyro

    @dataclasses.dataclass
    class Point3[ScalarType: (int, float)]:
        x: ScalarType
        y: ScalarType
        z: ScalarType
        frame_id: str

    @dataclasses.dataclass
    class Triangle:
        a: Point3[float]
        b: Point3[float]
        c: Point3[float]

    @dataclasses.dataclass
    class Args[ShapeType]:
        shape: ShapeType

    if __name__ == "__main__":
        args = tyro.cli(Args[Triangle])
        print(args)




.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./01_generics_py312.py --help</strong>
    <span style="font-weight: bold">usage:</span> ./01_generics_py312.py [-h] [OPTIONS]
    
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> -h, --help              <span style="font-weight: lighter">show</span><span style="font-weight: lighter"> this</span><span style="font-weight: lighter"> help</span><span style="font-weight: lighter"> message</span><span style="font-weight: lighter"> and</span><span style="font-weight: lighter"> exit</span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.a</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.b</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.c</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    </pre>
.. _example-02_generics:

Generics (Python <3.12)
-----------------------

The legacy :py:class:`typing.Generic` and :py:class:`typing.TypeVar` syntax for
generic types is also supported.


.. code-block:: python
    :linenos:

    # 02_generics.py
    import dataclasses
    from typing import Generic, TypeVar

    import tyro

    ScalarType = TypeVar("ScalarType", int, float)
    ShapeType = TypeVar("ShapeType")

    @dataclasses.dataclass
    class Point3(Generic[ScalarType]):
        x: ScalarType
        y: ScalarType
        z: ScalarType
        frame_id: str

    @dataclasses.dataclass
    class Triangle:
        a: Point3[float]
        b: Point3[float]
        c: Point3[float]

    @dataclasses.dataclass
    class Args(Generic[ShapeType]):
        shape: ShapeType

    if __name__ == "__main__":
        args = tyro.cli(Args[Triangle])
        print(args)




.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./02_generics.py --help</strong>
    <span style="font-weight: bold">usage:</span> ./02_generics.py [-h] [OPTIONS]
    
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> -h, --help              <span style="font-weight: lighter">show</span><span style="font-weight: lighter"> this</span><span style="font-weight: lighter"> help</span><span style="font-weight: lighter"> message</span><span style="font-weight: lighter"> and</span><span style="font-weight: lighter"> exit</span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.a</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.a.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.b</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.b.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">shape.c</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.x <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.y <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.z <span style="font-weight: bold">FLOAT       </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --shape.c.frame-id <span style="font-weight: bold">STR  </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    </pre>
.. _example-03_generic_subcommands:

Generic subcommands
-------------------

Just like standard classes, generic classes within unions can be selected
between using subcommands.


.. code-block:: python
    :linenos:

    # 03_generic_subcommands.py
    import dataclasses
    from pathlib import Path

    import tyro

    @dataclasses.dataclass
    class Sgd:
        lr: float = 1e-4

    @dataclasses.dataclass
    class Adam:
        lr: float = 3e-4
        betas: tuple[float, float] = (0.9, 0.999)

    @dataclasses.dataclass
    class Experiment[OptimizerT: (Adam, Sgd)]:
        path: Path
        opt: OptimizerT

    if __name__ == "__main__":
        args = tyro.cli(Experiment[Adam] | Experiment[Sgd])
        print(args)




.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_generic_subcommands.py --help</strong>
    <span style="font-weight: bold">usage:</span> ./03_generic_subcommands.py [-h] {experiment-adam,experiment-sgd}
    
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">options</span> <span style="font-weight: lighter; color: #808080">────────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> -h, --help           <span style="font-weight: lighter">show</span><span style="font-weight: lighter"> this</span><span style="font-weight: lighter"> help</span><span style="font-weight: lighter"> message</span><span style="font-weight: lighter"> and</span><span style="font-weight: lighter"> exit</span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">──────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">subcommands</span> <span style="font-weight: lighter; color: #808080">────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> <span style="color: #e60000">(required)                                          </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> <span style="font-weight: lighter"></span><span style="font-weight: lighter"> </span><span style="font-weight: lighter"> •</span><span style="font-weight: lighter"> </span>experiment-adam  <span style="font-weight: lighter">                               </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> <span style="font-weight: lighter"></span><span style="font-weight: lighter"> </span><span style="font-weight: lighter"> •</span><span style="font-weight: lighter"> </span>experiment-sgd   <span style="font-weight: lighter">                               </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">──────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_generic_subcommands.py experiment-adam --help</strong>
    <span style="font-weight: bold">usage:</span> ./03_generic_subcommands.py experiment-adam [-h] --path <span style="font-weight: bold">PATH</span> [--opt.lr <span style="font-weight: bold">FLOAT</span>] [--opt.betas <span style="font-weight: bold">FLOAT</span><span style="font-weight: bold"> FLOAT</span>]
    
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">options</span> <span style="font-weight: lighter; color: #808080">────────────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> -h, --help               <span style="font-weight: lighter">show</span><span style="font-weight: lighter"> this</span><span style="font-weight: lighter"> help</span><span style="font-weight: lighter"> message</span><span style="font-weight: lighter"> and</span><span style="font-weight: lighter"> exit</span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --path <span style="font-weight: bold">PATH              </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">──────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">opt</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">────────────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --opt.lr <span style="font-weight: bold">FLOAT           </span><span style="color: #008080">(default:</span><span style="color: #008080"> 0.0003)              </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --opt.betas <span style="font-weight: bold">FLOAT</span><span style="font-weight: bold"> FLOAT  </span><span style="color: #008080">(default:</span><span style="color: #008080"> 0.9</span><span style="color: #008080"> 0.999)           </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">──────────────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_generic_subcommands.py experiment-sgd --help</strong>
    <span style="font-weight: bold">usage:</span> ./03_generic_subcommands.py experiment-sgd [-h] --path <span style="font-weight: bold">PATH</span> [--opt.lr <span style="font-weight: bold">FLOAT</span>]
    
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> -h, --help      <span style="font-weight: lighter">show</span><span style="font-weight: lighter"> this</span><span style="font-weight: lighter"> help</span><span style="font-weight: lighter"> message</span><span style="font-weight: lighter"> and</span><span style="font-weight: lighter"> exit</span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">│</span> --path <span style="font-weight: bold">PATH     </span><span style="color: #e60000">(required)                     </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    <span style="font-weight: lighter; color: #808080">╭</span><span style="font-weight: lighter; color: #808080">─</span> <span style="font-weight: lighter; color: #808080">opt</span><span style="font-weight: lighter; color: #808080"> options</span> <span style="font-weight: lighter; color: #808080">───────────────────────────────────╮</span>
    <span style="font-weight: lighter; color: #808080">│</span> --opt.lr <span style="font-weight: bold">FLOAT  </span><span style="color: #008080">(default:</span><span style="color: #008080"> 0.0001)              </span> <span style="font-weight: lighter; color: #808080">│</span>
    <span style="font-weight: lighter; color: #808080">╰</span><span style="font-weight: lighter; color: #808080">─────────────────────────────────────────────────</span><span style="font-weight: lighter; color: #808080">╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_generic_subcommands.py experiment-adam --path /tmp --opt.lr 1e-3</strong>
    Experiment(path=PosixPath('/tmp'), opt=Adam(lr=0.001, betas=(0.9, 0.999)))
    </pre>