Question

Type of Union or Union of Types

In Python, is Type[Union[A, B, C]] the same as Union[Type[A], Type[B], Type[C]]? I think they are equivalent, and the interpreter seems to agree.

ChatGPT (which, from my past experience, tends to be wrong with this type of questions) disagrees so I was wondering which one is more correct.

To be clear: I want a union of the types of A, B or C, not a union of instances of A, B or C. The first option is shorter and IMHO more readable.

In other words, given these definitions:

class A:
    pass

class B:
    pass

class C:
    pass


def foo(my_class: Type[Union[A, B, C]]):
    pass

I expect this usage to be correct:

foo(A)   # pass the class A itself

But not this one:

foo(A()) # pass an instance of A
 3  72  3
1 Jan 1970

Solution

 6

They are the same. You can use reveal_type and check.

class A: ...
class B: ...
class C: ...

def something(a: type[A | B | C]) -> None:
    reveal_type(a)

def something_else(b: type[A] | type[B]| type[C]) -> None:
    reveal_type(b)
mypy main.py
main.py:6: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
main.py:9: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
pyright main.py 
  main.py:6:17 - information: Type of "a" is "type[A] | type[B] | type[C]"
  main.py:9:17 - information: Type of "b" is "type[A] | type[B] | type[C]"

Edit:

Older syntax

from typing import Union, Type
class A: ...
class B: ...
class C: ...

def something(a: type[A | B | C]) -> None:
    reveal_type(a)

def something_else(b: type[A] | type[B]| type[C]) -> None:
    reveal_type(b)

def old_something(c: Type[Union[A, B, C]]) -> None:
    reveal_type(c)

def old_something_else(d: Union[Type[A], Type[B], Type[C]]) -> None:
    reveal_type(d)
mypy main.py
main.py:7: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
main.py:10: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
main.py:13: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
main.py:16: note: Revealed type is "Union[type[main.A], type[main.B], type[main.C]]"
pyright main.py
  main.py:7:17 - information: Type of "a" is "type[A] | type[B] | type[C]"
  main.py:10:17 - information: Type of "b" is "type[A] | type[B] | type[C]"
  main.py:13:17 - information: Type of "c" is "type[A] | type[B] | type[C]"
  main.py:16:17 - information: Type of "d" is "type[A] | type[B] | type[C]"
2024-07-16
python_user