You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, unions created through typing.Union[A, B] and through the PEP-604 syntax A | B are at runtime instances of completely different types, and they differ in exactly what elements they accept. This is confusing and makes it harder for users to detect unions at runtime.
I propose to proceed in two steps:
Make typing.Union an alias for types.UnionType and make it so types.UnionType[A, B] works, accepting the same types Union accepts now.
Loosen the rules for what the | operator accepts to accept more types that are commonly used in unions.
I put up a first implementation at #105511. Some thoughts on the details:
I implemented it by making typing.Union just a re-export of types.UnionType, but I feel it might actually be more intuitive if typing.Union was the canonical name of the object, and types.UnionType was an alias. We could change the implementation to set the module and name differently.
The repr() of all unions changes to use the | syntax.
I added dummy __name__, __qualname__, and __origin__ fields to types.UnionType to satisfy some test_typing tests.
We no longer support writing to a union's __args__ attribute. A test relied on this, but nobody should have been assigning to __args__ anyway, so I'm fine with this change.
There's a couple of behavior changes around issubclass() and subclassing because types.UnionType is (unlike typing.Union) an actual type.
This broken an AST walker I had written for Python 3.9, after I upgraded all my Union[X, Y] to X | Y, something is expected to be purely syntactical change.
I think this was a mistake. types.UnionType was intentionally named so to avoid confusion with typing.Union (see #88895
). types.UnionType should not be subscriptable because it is not generic type (and if it was a generic type, subscription would have different semantic than for typing.Union). types.UnionType corresponds to typing._UnionGenericAlias, not typing.Union.
Activity
JelleZijlstra commentedon Jun 8, 2023
I put up a first implementation at #105511. Some thoughts on the details:
typing.Unionjust a re-export oftypes.UnionType, but I feel it might actually be more intuitive iftyping.Unionwas the canonical name of the object, andtypes.UnionTypewas an alias. We could change the implementation to set the module and name differently.|syntax.__name__,__qualname__, and__origin__fields totypes.UnionTypeto satisfy sometest_typingtests.__args__attribute. A test relied on this, but nobody should have been assigning to__args__anyway, so I'm fine with this change.issubclass()and subclassing becausetypes.UnionTypeis (unliketyping.Union) an actual type.tibbe commentedon Jun 14, 2023
This broken an AST walker I had written for Python 3.9, after I upgraded all my
Union[X, Y]toX | Y, something is expected to be purely syntactical change.samsonvd commentedon Sep 28, 2024
Will this also fix the issue of
unsupported operand type(s) for |: 'str' and ...when using a string reference of a type?i.e.
JelleZijlstra commentedon Sep 28, 2024
@marscapone, no, but other changes in Python 3.14 (PEP-649) will fix that case.
hauntsaninja commentedon Sep 28, 2024
See also https://mypy.readthedocs.io/en/stable/runtime_troubles.html and
from __future__ import annotations, for mostly solutions in Python 3.7 onwardsgh-105499: Merge typing.Union and types.UnionType (#105511)
Fix multiple issues with converting type hints to JSON Schema
Fix multiple issues with converting type hints to JSON Schema
Fix multiple issues with converting type hints to JSON Schema (#2379)
Drop deprecated `_UnionGenericAlias` on Python 3.14 and up
Drop deprecated `_UnionGenericAlias` on Python 3.14 and up
gh-105499: typing: Remove an unused function (#131946)
pythongh-105499: Defer "import warnings" in typing
gh-105499: Defer "import warnings" in typing (#132061)
changed test_legacy_union to test_typing_union. Changed behavior due to
changed test_legacy_union to test_typing_union. Changed behavior due to
changed test_legacy_union to test_typing_union. Changed behavior due to
serhiy-storchaka commentedon Jul 24, 2025
I think this was a mistake.
types.UnionTypewas intentionally named so to avoid confusion withtyping.Union(see #88895).
types.UnionTypeshould not be subscriptable because it is not generic type (and if it was a generic type, subscription would have different semantic than fortyping.Union).types.UnionTypecorresponds totyping._UnionGenericAlias, nottyping.Union.pythongh-137065: Unmerge types.UnionType and typing.Union
pythongh-137065: Unmerge types.UnionType and typing.Union
pythongh-137065: Revert "pythongh-105499: Merge typing.Union and type…
pythongh-137065: Revert "pythongh-105499: Merge typing.Union and type…
gh-105499: Avoid using `functools.reduce()` to reconstruct `Union` ob…
pythongh-105499: Avoid using `functools.reduce()` to reconstruct `Uni…