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.

The type statement is a soft keyword introduced in Python 3.12 (PEP 695) used to declare type aliases. It provides a dedicated, native syntax for defining both generic and non-generic type aliases, replacing the older typing.TypeAlias assignment method while introducing lazy evaluation, implicit variance inference, and strict scoping.

Syntax

The statement follows this general grammar:
type AliasName = TypeExpression
type GenericAliasName[TypeParameters] = TypeExpression

Technical Mechanics

1. Underlying Object (typing.TypeAliasType) When the Python interpreter executes a type statement, it does not simply assign the right-hand side to the left-hand side. Instead, it creates an instance of typing.TypeAliasType and binds it to the AliasName.
type Point = tuple[float, float]

print(type(Point))  # <class 'typing.TypeAliasType'>
2. Lazy Evaluation The TypeExpression on the right-hand side is lazily evaluated. The Python compiler wraps the expression in an implicit function. This allows the alias to reference names that have not yet been defined (forward references) without raising a NameError at runtime, eliminating the need for string literals. The actual value is only evaluated when explicitly requested via the __value__ attribute.
type NodeList = list[Node]  # 'Node' is not yet defined

class Node:
    pass


# Evaluation happens here
print(NodeList.__value__)  # list[__main__.Node]
3. Type Parameter Scoping When defining generic type aliases, the type statement introduces an annotation scope. Type parameters defined within the square brackets [...] are implicitly created and are strictly scoped to the TypeExpression. They do not leak into the surrounding module namespace.
type Mapping[K, V] = dict[K, V]


# K and V are valid within the statement, but undefined outside

# print(K) -> NameError: name 'K' is not defined
4. Implicit Variance Unlike the legacy typing.TypeVar instantiation which required explicit covariant=True or contravariant=True flags, type parameters declared via the type statement automatically infer their variance based on how they are used within the TypeExpression.

Generic Type Parameter Syntax

The square bracket syntax supports standard TypeVar declarations, bound types, constrained types, TypeVarTuple (variadic generics), and ParamSpec (callable signatures).
  • Standard Type Variables:
type Vector[T] = list[T]
  • Bound Type Variables (using : with a single type): Restricts the type variable to the specified type and its subclasses.
type FloatList[T: float] = list[T]
  • Constrained Type Variables (using : with a tuple of types): Restricts the type variable to exactly the specified types (no subclasses).
type NumberList[T: (int, float)] = list[T]
  • TypeVarTuple (using *):
type Shape[*Ts] = tuple[*Ts]
  • ParamSpec (using **):
import typing

type Callback[**P, R] = typing.Callable[P, R]

Runtime Introspection Attributes

Instances created by the type statement expose specific dunder attributes for runtime introspection:
  • __name__: The string name of the type alias.
  • __value__: The evaluated type expression (triggers lazy evaluation).
  • __type_params__: A tuple of the implicit type parameter objects (e.g., TypeVar instances) declared in the generic signature.
type Matrix[T] = list[list[T]]

print(Matrix.__name__)         # Matrix
print(Matrix.__type_params__)  # (T,)
print(Matrix.__value__)        # list[list[T]]
Master Python with Deep Grasping Methodology!Learn More