I'm trying to use typing with a function that has conditional parameters, that works like this:
from typing import Optional, Union
class Foo:
some_param_to_check: str = 'foo_name'
one_param_exclusive_to_foo: int
class Bar:
some_param_to_check: str = 'bar_name'
another_param_exclusive_to_bar: str
def some_process_that_returns_a_bool(
f_or_b: Union[Foo, Bar],
a_name: str,
) -> bool:
return f_or_b.some_param_to_check == a_name
def do_something_with_foo_or_bar(
foo: Optional[Foo],
bar: Optional[Bar],
some_name: str,
) -> bool:
if not foo and not bar:
raise ValueError('You need to specify either "foo" or "bar".')
# I added this explicit type hint after the first error, hoping it would solve the issue:
foo_or_bar: Union[Foo, Bar] # later becomes Union[Foo, Bar, None]
foo_or_bar = foo if foo else bar
return some_process_that_returns_a_bool(foo_or_bar, some_name)
foo_obj = Foo()
bar_obj = Bar()
# This will work:
do_something_with_foo_or_bar(foo_obj, bar_obj, 'test_string')
# This will also work:
do_something_with_foo_or_bar(foo_obj, None, 'test_string')
# This too:
do_something_with_foo_or_bar(None, bar_obj, 'test_string')
# But this should not:
do_something_with_foo_or_bar(None, None, 'test_string')
To add more context:
The function works by expecting foo, or, if not available, bar. If foo is not None, bar will essentially be ignored.
When checking with mypy, it complains about:
Incompatible types in assignment (expression has type "Union[Foo, Bar, None]", variable has type "Union[Foo, Bar]"
(I'm guessing because of the Optional in the parameter type hints.)
If I then add None as the type hint for foo_or_bar then the error becomes:
error: Item "None" of "Union[Foo, Bar, None]" has no attribute "some_param_to_check"
How would I fix this so that mypy stops complaining (while still keeping the type hints)?