Generics

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

Generics (3.12+)

This example uses syntax introduced in Python 3.12 (PEP 695).

Note

If used in conjunction with from __future__ import annotations, the updated type parameter syntax requires Python 3.12.4 or newer. For technical details, see this CPython PR.

 1# 01_generics_py312.py
 2import dataclasses
 3
 4import tyro
 5
 6@dataclasses.dataclass
 7class Point3[ScalarType: (int, float)]:
 8    x: ScalarType
 9    y: ScalarType
10    z: ScalarType
11    frame_id: str
12
13@dataclasses.dataclass
14class Triangle:
15    a: Point3[float]
16    b: Point3[float]
17    c: Point3[float]
18
19@dataclasses.dataclass
20class Args[ShapeType]:
21    shape: ShapeType
22
23if __name__ == "__main__":
24    args = tyro.cli(Args[Triangle])
25    print(args)
$ python ./01_generics_py312.py --help
usage: 01_generics_py312.py [-h] [OPTIONS]

╭─ options ───────────────────────────────────────────────╮
 -h, --help              show this help message and exit 
╰─────────────────────────────────────────────────────────╯
╭─ shape.a options ───────────────────────────────────────╮
 --shape.a.x FLOAT       (required)                      
 --shape.a.y FLOAT       (required)                      
 --shape.a.z FLOAT       (required)                      
 --shape.a.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯
╭─ shape.b options ───────────────────────────────────────╮
 --shape.b.x FLOAT       (required)                      
 --shape.b.y FLOAT       (required)                      
 --shape.b.z FLOAT       (required)                      
 --shape.b.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯
╭─ shape.c options ───────────────────────────────────────╮
 --shape.c.x FLOAT       (required)                      
 --shape.c.y FLOAT       (required)                      
 --shape.c.z FLOAT       (required)                      
 --shape.c.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯

Generics (Legacy)

The legacy typing.Generic and typing.TypeVar syntax for generic types is also supported.

 1# 02_generics.py
 2import dataclasses
 3from typing import Generic, TypeVar
 4
 5import tyro
 6
 7ScalarType = TypeVar("ScalarType", int, float)
 8ShapeType = TypeVar("ShapeType")
 9
10@dataclasses.dataclass(frozen=True)
11class Point3(Generic[ScalarType]):
12    x: ScalarType
13    y: ScalarType
14    z: ScalarType
15    frame_id: str
16
17@dataclasses.dataclass(frozen=True)
18class Triangle:
19    a: Point3[float]
20    b: Point3[float]
21    c: Point3[float]
22
23@dataclasses.dataclass(frozen=True)
24class Args(Generic[ShapeType]):
25    shape: ShapeType
26
27if __name__ == "__main__":
28    args = tyro.cli(Args[Triangle])
29    print(args)
$ python ./02_generics.py --help
usage: 02_generics.py [-h] [OPTIONS]

╭─ options ───────────────────────────────────────────────╮
 -h, --help              show this help message and exit 
╰─────────────────────────────────────────────────────────╯
╭─ shape.a options ───────────────────────────────────────╮
 --shape.a.x FLOAT       (required)                      
 --shape.a.y FLOAT       (required)                      
 --shape.a.z FLOAT       (required)                      
 --shape.a.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯
╭─ shape.b options ───────────────────────────────────────╮
 --shape.b.x FLOAT       (required)                      
 --shape.b.y FLOAT       (required)                      
 --shape.b.z FLOAT       (required)                      
 --shape.b.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯
╭─ shape.c options ───────────────────────────────────────╮
 --shape.c.x FLOAT       (required)                      
 --shape.c.y FLOAT       (required)                      
 --shape.c.z FLOAT       (required)                      
 --shape.c.frame-id STR  (required)                      
╰─────────────────────────────────────────────────────────╯