:class:`str` and the return type :class:`str`. Subtypes are accepted as
arguments.
+.. _type-aliases:
+
Type aliases
============
.. versionadded:: 3.5.4
.. versionadded:: 3.6.2
+.. data:: TypeAlias
+
+ Special annotation for explicitly declaring a :ref:`type alias <type-aliases>`.
+ For example::
+
+ from typing import TypeAlias
+
+ Factors: TypeAlias = list[int]
+
+ .. versionadded:: 3.10
+
Special forms
"""""""""""""
* :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used
to require that all the iterables have an equal length.
-PEP604: New Type Operator
--------------------------
+PEP 613: TypeAlias Annotation
+-----------------------------
+
+:pep:`484` introduced the concept of type aliases, only requiring them to be
+top-level unannotated assignments. This simplicity sometimes made it difficult
+for type checkers to distinguish between type aliases and ordinary assignments,
+especially when forward references or invalid types were involved. Compare::
+
+ StrCache = 'Cache[str]' # a type alias
+ LOG_PREFIX = 'LOG[DEBUG]' # a module constant
+
+Now the :mod:`typing` module has a special annotation :data:`TypeAlias` to
+declare type aliases more explicitly::
+
+ StrCache: TypeAlias = 'Cache[str]' # a type alias
+ LOG_PREFIX = 'LOG[DEBUG]' # a module constant
+
+See :pep:`613` for more details.
+
+(Contributed by Mikhail Golubev in :issue:`41923`.)
+
+PEP604: New Type Union Operator
+-------------------------------
A new type union operator was introduced which enables the syntax ``X | Y``.
This provides a cleaner way of expressing 'either type X or type Y' instead of
from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match
from typing import Annotated, ForwardRef
+from typing import TypeAlias
import abc
import typing
import weakref
self.assertEqual(X[int], List[Annotated[int, 5]])
+class TypeAliasTests(BaseTestCase):
+ def test_canonical_usage_with_variable_annotation(self):
+ Alias: TypeAlias = Employee
+
+ def test_canonical_usage_with_type_comment(self):
+ Alias = Employee # type: TypeAlias
+
+ def test_cannot_instantiate(self):
+ with self.assertRaises(TypeError):
+ TypeAlias()
+
+ def test_no_isinstance(self):
+ with self.assertRaises(TypeError):
+ isinstance(42, TypeAlias)
+
+ def test_no_issubclass(self):
+ with self.assertRaises(TypeError):
+ issubclass(Employee, TypeAlias)
+
+ with self.assertRaises(TypeError):
+ issubclass(TypeAlias, Employee)
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class C(TypeAlias):
+ pass
+
+ with self.assertRaises(TypeError):
+ class C(type(TypeAlias)):
+ pass
+
+ def test_repr(self):
+ self.assertEqual(repr(TypeAlias), 'typing.TypeAlias')
+
+ def test_cannot_subscript(self):
+ with self.assertRaises(TypeError):
+ TypeAlias[int]
+
+
class AllTests(BaseTestCase):
"""Tests for __all__."""
'runtime_checkable',
'Text',
'TYPE_CHECKING',
+ 'TypeAlias',
]
# The pseudo-submodules 're' and 'io' are part of the public
return _GenericAlias(self, parameters)
+@_SpecialForm
+def TypeAlias(self, parameters):
+ """Special marker indicating that an assignment should
+ be recognized as a proper type alias definition by type
+ checkers.
+
+ For example::
+
+ Predicate: TypeAlias = Callable[..., bool]
+
+ It's invalid when used anywhere except as in the example above.
+ """
+ raise TypeError(f"{self} is not subscriptable")
+
+
class ForwardRef(_Final, _root=True):
"""Internal wrapper to hold a forward reference."""
Tim Golden
Yonatan Goldschmidt
Mark Gollahon
+Mikhail Golubev
Guilherme Gonçalves
Tiago Gonçalves
Chris Gonnerman
--- /dev/null
+Implement :pep:`613`, introducing :data:`typing.TypeAlias` annotation.