Having a function that takes `Optional[T]` as an input and returns `T` (A type var) works incorrectly if T is an union
Bug Report
Having a function that takes Optional[T] as an input and returns T (A type var) works incorrectly if T is an union.
To Reproduce
from typing import TypeVar
class A:
pass
class B:
pass
T = TypeVar("T")
def make_non_optional(value: T | None) -> T:
if value is None:
raise ValueError("Value is None")
return value
def make_non_optimal_simple_example() -> A:
my_value: A | None = None
return make_non_optional(my_value) # This works as expected
def make_non_optimal_complex_example_broken() -> A | B:
my_value: A | B | None = None
return make_non_optional(my_value) # error: Incompatible return value type (got "object", expected "A | B") [return-value]
Expected Behavior
When calling make_non_optional(my_value) with A | B | None the returned type should be A | B
Actual Behavior
It has object type as the return type
Your Environment
Mypy version used:
$ mypy --version
mypy 1.10.0 (compiled: yes)
Python version used:
$ python --version
Python 3.12.2
Mypy command-line flags: none
Mypy configuration options from mypy.ini (and other config files): none
This behavior stems from the fact that mypy's constraint solver uses a join operator rather than unions. The join of A and B is object, which explains the error message you're seeing here.
Does anyone know of a good workaround for this (other than the obvious # type: ignore)??
I have a code-base where this is coming up repeatedly...