Definition
A TypeVar gives a type checker a name for a relationship. If a function accepts and returns T, the return type follows the argument type instead of collapsing to a broad common type.
It does not create a runtime validation rule. Python still receives ordinary objects, and the checker reasons about calls before execution.
Import and first use
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T:
return items[0]
print("[state] declared type variable:", T)
print("[result] first integer:", first([10, 20, 30]))
print("[result] first string:", first(["python", "typing"]))
The checker substitutes int for T in the first call and str in the second. One declaration describes both calls while preserving their distinct result types.
Constraints and bounds
Constraints enumerate permitted alternatives:
Text = TypeVar("Text", str, bytes)
A bound requires compatibility with one upper type:
from collections.abc import Sized
SizedT = TypeVar("SizedT", bound=Sized)
Constraints and bounds answer different questions. Use constraints when the implementation supports a closed set of alternatives. Use a bound when callers may supply any compatible subtype.
Common mistake
Introducing T does not automatically connect types. The same variable must appear in positions whose relationship matters:
T = TypeVar("T")
def disconnected(value: object) -> T: # T cannot be inferred from value
...
Prefer a concrete return type when no input or enclosing generic supplies the type variable.
Version note
Python 3.12 added type-parameter syntax such as def first[T](items: list[T]) -> T. The TypeVar spelling remains necessary for older supported versions and for APIs that construct type variables dynamically.
Primary sourceOfficial Python documentation ↗