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.
Bug Report
Having a function that takes
Optional[T]
as an input and returnsT
(A type var) works incorrectly if T is an union.To Reproduce
Expected Behavior
When calling
make_non_optional(my_value)
withA | B | None
the returned type should beA | B
Actual Behavior
It has
object
type as the return typeYour Environment
Mypy version used:
Python version used:
Mypy command-line flags: none
Mypy configuration options from
mypy.ini
(and other config files): none