I'm trying to understand why in the following code:
from typing import Optional, Union
def foo(arg: Union[float, tuple[float, float], tuple[float, None]]) -> None:
pass
a: float = 1.0
b: Optional[float] = None
foo((a, b))
Mypy considers (a, b) as incompatible with the signature of foo:
$ mypy typetest.py
typetest.py:9: error: Argument 1 to "foo" has incompatible type "Tuple[float, Optional[float]]"; expected "Union[float, Tuple[float, float], Tuple[float, None]]
My type annotation suggests b could only ever be None or float, so in practice, I'll only ever pass tuple[float, float] or tuple[float, None].
I'm running into this at work, as I'm trying to write a wrapper around requests.Session with typeshed's type annotations for requests installed. There, the parameter timeout is annotated in the same way as the arg param above:
Union[float, tuple[float, float], tuple[float, None]]
and I'm trying to pass it something annotated as Optional[float] and I just want to know what is the correct thing to do here.
Do I need to explicitly pass None when b is None or cast it as float when it is not?
I am on Python 3.9.