@@ -254,9 +254,8 @@ A ``TypeExpr`` value represents a :ref:`type expression <typing:type-expression>
254254such as ``str | None ``, ``dict[str, int] ``, or ``MyTypedDict ``.
255255A ``TypeExpr `` type is written as
256256``TypeExpr[T] `` where ``T `` is a type or a type variable. It can also be
257- written without brackets as just ``TypeExpr ``, in which case a type
258- checker should apply its usual type inference mechanisms to determine
259- the type of its argument, possibly ``Any ``.
257+ written without brackets as just ``TypeExpr ``, which is treated the same as
258+ to ``TypeExpr[Any] ``.
260259
261260
262261Using TypeExprs
@@ -278,7 +277,6 @@ or a variable type:
278277::
279278
280279 STR_TYPE: TypeExpr = str # variable type
281- assert_type(STR_TYPE, TypeExpr[str])
282280
283281Note however that an *unannotated * variable assigned a type expression literal
284282will not be inferred to be of ``TypeExpr `` type by type checkers because PEP
@@ -352,7 +350,7 @@ not spell a type are not ``TypeExpr`` values.
352350::
353351
354352 OPTIONAL_INT_TYPE: TypeExpr = TypeExpr[int | None] # OK
355- assert isassignable(Optional[ int] , OPTIONAL_INT_TYPE)
353+ assert isassignable(int | None , OPTIONAL_INT_TYPE)
356354
357355.. _non_universal_typeexpr :
358356
@@ -442,14 +440,29 @@ so must be disambiguated based on its argument type:
442440- As a value expression, ``Annotated[x, ...] `` has type ``object ``
443441 if ``x `` has a type that is not ``type[C] `` or ``TypeExpr[T] ``.
444442
445- **Union **: The type expression ``T1 | T2 `` is ambiguous with the value ``int1 | int2 ``,
446- so must be disambiguated based on its argument type:
443+ **Union **: The type expression ``T1 | T2 `` is ambiguous with
444+ the value ``int1 | int2 ``, ``set1 | set2 ``, ``dict1 | dict2 ``, and more,
445+ so must be disambiguated based on its argument types:
446+
447+ - As a value expression, ``x | y `` has type equal to the return type of ``type(x).__or__ ``
448+ if ``type(x) `` overrides the ``__or__ `` method.
449+
450+ - When ``x `` has type ``builtins.type ``, ``types.GenericAlias ``, or the
451+ internal type of a typing special form, ``type(x).__or__ `` has a return type
452+ in the format ``TypeExpr[T1 | T2] ``.
453+
454+ - As a value expression, ``x | y `` has type equal to the return type of ``type(y).__ror__ ``
455+ if ``type(y) `` overrides the ``__ror__ `` method.
456+
457+ - When ``y `` has type ``builtins.type ``, ``types.GenericAlias ``, or the
458+ internal type of a typing special form, ``type(y).__ror__ `` has a return type
459+ in the format ``TypeExpr[T1 | T2] ``.
447460
448- - As a value expression, ``x | y `` has type ``TypeExpr[x | y] ``
449- if `` x `` has type `` TypeExpr[t1] `` (or `` type[t1] ``)
450- and `` y `` has type `` TypeExpr[t2] `` (or `` type[t2] ``).
451- - As a value expression, `` x | y `` has type `` int ``
452- if `` x `` has type `` int `` and `` y `` has type `` int ``
461+ - As a value expression, ``x | y `` has type ``UnionType ``
462+ in all other situations.
463+
464+ - This rule is intended to be consistent with the preexisting fallback rule
465+ used by static type checkers.
453466
454467The **stringified type expression ** ``"T" `` is ambiguous with both
455468the stringified annotation expression ``"T" ``
@@ -466,71 +479,24 @@ New kinds of type expressions that are introduced should define how they
466479will be recognized in a value expression context.
467480
468481
469- Implicit Annotation Expression Values
470- '''''''''''''''''''''''''''''''''''''
471-
472- Although this PEP is mostly concerned with *type expressions * rather than
473- *annotation expressions *, it is straightforward to extend the rules for
474- :ref: `recognizing type expressions <implicit_typeexpr_values >`
475- to similar rules for recognizing annotation expressions,
476- so this PEP takes the opportunity to define those rules as well:
477-
478- The following **unparameterized annotation expressions ** can be recognized unambiguously:
479-
480- - As a value expression, ``X `` has type ``object ``,
481- for each of the following values of X:
482-
483- - ``<TypeAlias> ``
484-
485- The following **parameterized annotation expressions ** can be recognized unambiguously:
486-
487- - As a value expression, ``X `` has type ``object ``,
488- for each of the following values of X:
489-
490- - ``<Required> '[' ... ']' ``
491- - ``<NotRequired> '[' ... ']' ``
492- - ``<ReadOnly> '[' ... ']' ``
493- - ``<ClassVar> '[' ... ']' ``
494- - ``<Final> '[' ... ']' ``
495- - ``<InitVar> '[' ... ']' ``
496- - ``<Unpack> '[' ... ']' ``
497-
498- **Annotated **: The annotation expression ``Annotated[...] `` is ambiguous with
499- the type expression ``Annotated[...] ``,
500- so must be :ref: `disambiguated based on its argument type <recognizing_annotated >`.
501-
502- The following **syntactic annotation expressions **
503- cannot be recognized in a value expression context at all:
504-
505- - ``'*' unpackable ``
506- - ``name '.' 'args' `` (where ``name `` must be an in-scope ParamSpec)
507- - ``name '.' 'kwargs' `` (where ``name `` must be an in-scope ParamSpec)
508-
509- The **stringified annotation expression ** ``"T" `` is ambiguous with both
510- the stringified type expression ``"T" ``
511- and the string literal ``"T" ``, and
512- cannot be recognized in a value expression context at all:
513-
514- - As a value expression, ``"T" `` continues to have type ``Literal["T"] ``.
515-
516- No other kinds of annotation expressions currently exist.
517-
518- New kinds of annotation expressions that are introduced should define how they
519- will (or will not) be recognized in a value expression context.
520-
521-
522482Literal[] TypeExprs
523483'''''''''''''''''''
524484
525- To simplify static type checking, a ``Literal[...] `` value is *not *
526- considered assignable to a ``TypeExpr `` variable even if all of its members
527- spell valid types :
485+ A value of ``Literal[...] `` type is *not * considered assignable to
486+ a ``TypeExpr `` variable even if all of its members spell valid types because
487+ dynamic values are not allowed in type expressions :
528488
529489::
530490
531491 STRS_TYPE_NAME: Literal['str', 'list[str]'] = 'str'
532492 STRS_TYPE: TypeExpr = STRS_TYPE_NAME # ERROR: Literal[] value is not a TypeExpr
533493
494+ However ``Literal[...] `` itself is still a ``TypeExpr ``:
495+
496+ ::
497+
498+ DIRECTION_TYPE: TypeExpr[Literal['left', 'right']] = Literal['left', 'right'] # OK
499+
534500
535501Static vs. Runtime Representations of TypeExprs
536502'''''''''''''''''''''''''''''''''''''''''''''''
@@ -569,19 +535,35 @@ Subtyping
569535Whether a ``TypeExpr `` value can be assigned from one variable to another is
570536determined by the following rules:
571537
538+ Relationship with type
539+ ''''''''''''''''''''''
540+
572541``TypeExpr[] `` is covariant in its argument type, just like ``type[] ``:
573542
574543- ``TypeExpr[T1] `` is a subtype of ``TypeExpr[T2] `` iff ``T1 `` is a
575544 subtype of ``T2 ``.
576545- ``type[C1] `` is a subtype of ``TypeExpr[C2] `` iff ``C1 `` is a subtype
577546 of ``C2 ``.
578547
579- A plain ``type `` can be assigned to a plain ``TypeExpr `` but not the
580- other way around:
548+ An unparameterized ``type `` can be assigned to an unparameterized ``TypeExpr ``
549+ but not the other way around:
581550
582551- ``type[Any] `` is assignable to ``TypeExpr[Any] ``. (But not the
583552 other way around.)
584553
554+ Relationship with UnionType
555+ '''''''''''''''''''''''''''
556+
557+ ``TypeExpr[U] `` is a subtype of ``UnionType `` iff ``U `` is
558+ the type expression ``X | Y | ... ``:
559+
560+ - ``TypeExpr[X | Y | ...] `` is a subtype of ``UnionType ``.
561+
562+ ``UnionType `` is assignable to ``TypeExpr[Any] ``.
563+
564+ Relationship with object
565+ ''''''''''''''''''''''''
566+
585567``TypeExpr[] `` is a kind of ``object ``, just like ``type[] ``:
586568
587569- ``TypeExpr[T] `` for any ``T `` is a subtype of ``object ``.
@@ -623,11 +605,33 @@ Changed signatures
623605''''''''''''''''''
624606
625607The following signatures related to type expressions introduce
626- ``TypeExpr `` where previously ``object `` existed:
608+ ``TypeExpr `` where previously ``object `` or `` Any `` existed:
627609
628610- ``typing.cast ``
629611- ``typing.assert_type ``
630612
613+ The following signatures transforming union type expressions introduce
614+ ``TypeExpr `` where previously ``UnionType `` existed so that a more-precise
615+ ``TypeExpr `` type can be inferred:
616+
617+ - ``builtins.type[T].__or__ ``
618+
619+ - Old: ``def __or__(self, value: Any, /) -> types.UnionType: ... ``
620+ - New: ``def __or__[T2](self, value: TypeExpr[T2], /) -> TypeExpr[T | T2]: ... ``
621+
622+ - ``builtins.type[T].__ror__ ``
623+
624+ - Old: ``def __ror__(self, value: Any, /) -> types.UnionType: ... ``
625+ - New: ``def __ror__[T1](self, value: TypeExpr[T1], /) -> TypeExpr[T1 | T]: ... ``
626+
627+ - ``types.GenericAlias.{__or__,__ror__} ``
628+ - «the internal type of a typing special form»``.{__or__,__ror__} ``
629+
630+ However the implementations of those methods continue to return ``UnionType ``
631+ instances at runtime so that runtime ``isinstance `` checks like
632+ ``isinstance('42', int | str) `` and ``isinstance(int | str, UnionType) ``
633+ continue to work.
634+
631635
632636Unchanged signatures
633637''''''''''''''''''''
@@ -662,12 +666,32 @@ not propose those changes now:
662666
663667 - Returns annotation expressions
664668
669+ The following signatures accepting union type expressions continue
670+ to use ``UnionType ``:
671+
672+ - ``builtins.isinstance ``
673+ - ``builtins.issubclass ``
674+ - ``typing.get_origin `` (used in an ``@overload ``)
675+
676+ The following signatures transforming union type expressions continue
677+ to use ``UnionType `` because it is not possible to infer a more-precise
678+ ``TypeExpr `` type:
679+
680+ - ``types.UnionType.{__or__,__ror__} ``
681+
665682
666683Backwards Compatibility
667684=======================
668685
669- Previously the rules for recognizing type expression objects
670- in a value expression context were not defined, so static type checkers
686+ As a value expression, ``X | Y `` previously had type ``UnionType `` (via :pep: `604 `)
687+ but this PEP gives it the more-precise static type ``TypeExpr[X | Y] ``
688+ (a subtype of ``UnionType ``) while continuing to return a ``UnionType `` instance at runtime.
689+ Preserving compability with ``UnionType `` is important because ``UnionType ``
690+ supports ``isinstance `` checks, unlike ``TypeExpr ``, and existing code relies
691+ on being able to perform those checks.
692+
693+ The rules for recognizing other kinds of type expression objects
694+ in a value expression context were not previously defined, so static type checkers
671695`varied in what types were assigned <https://discuss.python.org/t/typeform-spelling-for-a-type-annotation-object-at-runtime/51435/34 >`_
672696to such objects. Existing programs manipulating type expression objects
673697were already limited in manipulating them as plain ``object `` values,
@@ -711,12 +735,38 @@ assigned to variables and manipulated like any other data in a program:
711735 ``TypeExpr[] `` is how you spell the type of a variable containing a
712736type annotation object describing a type.
713737
714- ``TypeExpr[] `` is similar to ``type[] ``, but ``type[] `` can only used to
738+ ``TypeExpr[] `` is similar to ``type[] ``, but ``type[] `` can only
715739spell simple **class objects ** like ``int ``, ``str ``, ``list ``, or ``MyClass ``.
716740``TypeExpr[] `` by contrast can additionally spell more complex types,
717741including those with brackets (like ``list[int] ``) or pipes (like ``int | None ``),
718742and including special types like ``Any ``, ``LiteralString ``, or ``Never ``.
719743
744+ A ``TypeExpr `` variable looks similar to a ``TypeAlias `` definition, but
745+ can only be used where a dynamic value is expected.
746+ ``TypeAlias `` (and the ``type `` statement) by contrast define a name that can
747+ be used where a fixed type is expected:
748+
749+ - Okay, but discouraged in Python 3.12+:
750+
751+ ::
752+
753+ MaybeFloat: TypeAlias = float | None
754+ def sqrt(n: float) -> MaybeFloat: ...
755+
756+ - Yes:
757+
758+ ::
759+
760+ type MaybeFloat = float | None
761+ def sqrt(n: float) -> MaybeFloat: ...
762+
763+ - No:
764+
765+ ::
766+
767+ maybe_float: TypeExpr = float | None
768+ def sqrt(n: float) -> maybe_float: ... # ERROR: Can't use TypeExpr value in a type annotation
769+
720770It is uncommon for a programmer to define their *own * function which accepts
721771a ``TypeExpr `` parameter or returns a ``TypeExpr `` value. Instead it is more common
722772for a programmer to pass a literal type expression to an *existing * function
@@ -891,8 +941,9 @@ The following will be true when
891941`mypy#9773 <https://github.com/python/mypy/issues/9773 >`__ is implemented:
892942
893943 The mypy type checker supports ``TypeExpr `` types.
894- A reference implementation of the runtime component is provided in the
895- ``typing_extensions `` module.
944+
945+ A reference implementation of the runtime component is provided in the
946+ ``typing_extensions `` module.
896947
897948
898949Rejected Ideas
0 commit comments