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.TypeVarTuple is a type variable construct introduced in Python 3.11 (PEP 646) that enables variadic generics. Unlike a standard TypeVar, which binds to a single type, a TypeVarTuple binds to an arbitrary number of types, effectively representing a tuple of types. This allows static type checkers to capture, preserve, and validate the exact sequence and arity of types passed to a generic class or function.

Instantiation and Unpacking

A TypeVarTuple is instantiated similarly to a standard TypeVar, taking a string matching the variable name.
from typing import TypeVarTuple

Ts = TypeVarTuple('Ts')
When applied within type hints, a TypeVarTuple must be unpacked to indicate to the type checker that the variable represents a sequence of types rather than a single type. This is achieved using either the * (star) operator or typing.Unpack, depending on syntactic validity. Within type brackets (such as Generic or Tuple), the * operator is used:
from typing import Generic, TypeVarTuple

Ts = TypeVarTuple('Ts')

class VariadicContainer(Generic[*Ts]):
    pass


# Instantiation:

# VariadicContainer[int, str, bool]

# Here, *Ts binds to the type sequence (int, str, bool)

Combining with Standard Type Variables

A TypeVarTuple can be combined with standard TypeVar instances within a Generic parameter list. The type checker resolves the bindings positionally.
from typing import TypeVar, TypeVarTuple, Generic

T = TypeVar('T')
Ts = TypeVarTuple('Ts')

class MixedContainer(Generic[T, *Ts]):
    pass


# In MixedContainer[int, float, str]:

# T binds to `int`

# *Ts binds to `(float, str)`

Application in Signatures

TypeVarTuple is heavily utilized in function signatures to type-check variadic positional arguments and to maintain type parity between inputs and outputs.

With Tuple

When unpacked inside a Tuple, it defines a tuple with a specific, yet generic, sequence of types. Because TypeVarTuple preserves the exact order of types, it can be used to safely type operations like appending to a tuple.
from typing import Tuple, TypeVarTuple

Ts = TypeVarTuple('Ts')

def append_item(data: Tuple[*Ts], item: int) -> Tuple[*Ts, int]:
    ...

With Callable and Unpack

When specifying that a Callable accepts an arbitrary sequence of arguments, the * operator is used inside the callable’s argument list. However, when annotating the actual variadic positional arguments (*args) in the function signature, using the * operator (e.g., *args: *Ts) raises a SyntaxError because * cannot be used as a standalone type annotation expression. In this context, typing.Unpack is mandatory.
from typing import Callable, TypeVarTuple, Unpack

Ts = TypeVarTuple('Ts')

def invoke_with_args(func: Callable[[*Ts], None], *args: Unpack[Ts]) -> None:
    ...
Note: Unpack is also required when using TypeVarTuple in older Python versions via typing_extensions, as the * operator inside type brackets is only valid syntax in Python 3.11+.

Structural Rules and Limitations

  1. Single Instance Limit: A generic class or function signature can contain at most one TypeVarTuple. Constructs like Generic[*Ts1, *Ts2] are invalid because the type checker cannot unambiguously resolve the boundary between the two variadic sequences.
  2. No Bounds or Constraints: Unlike TypeVar, TypeVarTuple does not currently support upper bounds (bound=...) or type constraints (TypeVar('T', int, str)). It strictly accepts any sequence of types.
  3. Mandatory Unpacking: With very few exceptions (such as type aliases in specific contexts), a TypeVarTuple must always be unpacked using either the * operator or typing.Unpack when used in a type expression.
  4. Empty Binding: A TypeVarTuple can bind to zero types. For example, VariadicContainer[()] results in *Ts binding to an empty sequence.
Master Python with Deep Grasping Methodology!Learn More