Type-preserving generic functions
A function should return the same element type represented by its input.
Python · Type Alias
TypeVar creates a named type variable for generic functions, classes, and type aliases. Static type checkers use it to preserve relationships between types, while Python does not enforce the annotation at runtime.
TypeVar creates a named type variable that can parameterize generic functions, classes, and type aliases. A checker infers one type for each use, while optional constraints, bounds, or variance control the permitted relationships; Python itself does not enforce these annotations at runtime.
typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)| Name | Type | Description |
|---|---|---|
name | str | The variable name, conventionally a short identifier such as T. |
*constraints | type | Optional permitted types; inference selects from these constraints. |
bound | type | None | Optional upper bound; the inferred type must be a subtype of it. |
covariant | bool | Whether the manually created variable is covariant. |
contravariant | bool | Whether the manually created variable is contravariant. |
infer_variance | bool | Whether a type checker should infer variance. |
default | type | Optional default type for the type parameter. |
A type-variable object used by static type checkers as a parameter for generic declarations.
from collections.abc import Sequence
from typing import TypeVar
T = TypeVar("T")
def first(items: Sequence[T]) -> T:
return items[0]
print(first(["a", "b"]))
print(first([1, 2]))The same function preserves the element type of each sequence for static type checkers.
A function should return the same element type represented by its input.
Several classes or aliases share one reusable placeholder type.
An API accepts a family of related types but needs an upper capability limit.
A generic container has a deliberate subtype direction in its API.
TypeVar declares a type variable for generic functions, classes, or type aliases. For example, using the same T in a sequence parameter and return annotation tells a type checker that the returned element corresponds to the input element type.
Follow-up: How do constraints differ from a bound? Constraints choose among the listed types, while a bound allows any subtype of the specified upper type.
TypeVar accepts a name plus optional constraints, a bound, and variance settings. An unconstrained variable may represent any type; constraints limit it to specific alternatives, and a bound limits it to the bound or its subtypes.
Follow-up: What happens when a TypeVar is used more than once in one signature? The type checker generally infers a consistent solution for that variable across the use, rather than treating each occurrence as unrelated.
Type variables are primarily for static type checkers, and Python does not enforce function and variable annotations at runtime. Therefore, TypeVar improves editor and checker feedback without changing ordinary runtime execution.
Follow-up: When should modern code prefer type-parameter syntax? For generic functions, classes, and aliases, the documentation identifies dedicated type-parameter syntax as the preferred construction; manual TypeVar remains useful when a reusable named variable is desired.
GenericTypeAliasTypeVarTupleParamSpectyping