I'm trying to use overloading to make the return type of a variadic function depend on the type of its arguments in a certain way. Specifically, I want the return type to be X if and only if any of its arguments is of type X.
Consider the following minimal example:
from typing import overload
class Safe:
pass
class Dangerous:
pass
@overload
def combine(*args: Safe) -> Safe: ...
@overload
def combine(*args: Safe | Dangerous) -> Safe | Dangerous: ...
def combine(*args: Safe | Dangerous) -> Safe | Dangerous:
if all(isinstance(arg, Safe) for arg in args):
return Safe()
else:
return Dangerous()
reveal_type(combine())
reveal_type(combine(Safe()))
reveal_type(combine(Dangerous()))
reveal_type(combine(Safe(), Safe()))
reveal_type(combine(Safe(), Dangerous()))
This outputs
example.py:21: note: Revealed type is "example.Safe"
example.py:22: note: Revealed type is "example.Safe"
example.py:23: note: Revealed type is "Union[example.Safe, example.Dangerous]"
example.py:24: note: Revealed type is "example.Safe"
example.py:25: note: Revealed type is "Union[example.Safe, example.Dangerous]"
Success: no issues found in 1 source file
I want to set things up so that the inferred types of combine(Dangerous())
and combine(Safe(), Dangerous())
, for example, are Dangerous
rather than Safe | Dangerous
. Changing the return type of the second overload to just Dangerous
yields an error:
example.py:10: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]
example.py:21: note: Revealed type is "example.Safe"
example.py:22: note: Revealed type is "example.Safe"
example.py:23: note: Revealed type is "example.Dangerous"
example.py:24: note: Revealed type is "example.Safe"
example.py:25: note: Revealed type is "example.Dangerous"
Found 1 error in 1 file (checked 1 source file)
Thus it seems that I need a way to annotate the second overload to explicitly state that at least one of its arguments is Dangerous
. Is there a way to do this?
It occurs to me that the desired type for the argument sequence is Sequence[Safe | Dangerous] - Sequence[Safe]
, but I don't think type subtraction is supported yet.