Simple example of what's confusing me:
from typing import Callable, List, Union
Value = Union[bool, int, str]
Helper = Callable[[Value], List[Value]]
def func_with_alias(aa: Value) -> List[Value]:
return []
def func_with_type(aa: bool) -> List[Value]:
return []
your_func1: Helper = func_with_alias
your_func2: Helper = func_with_type
mypy complains that "your_func2" has an incompatible type:
error: Incompatible types in assignment (expression has type "Callable[[bool], List[Union[bool, int, str]]]", variable has type "Callable[[Union[bool, int, str]], List[Union[bool, int, str]]]")
Why doesn't it let me do this, as bool
is in Union[bool, int, str]
?
❯ mypy --version
mypy 0.782
Let's look at what you're saying with your type definitions:
Value = Union[bool, int, str]
A Value can be either a boolean, an integer or a string.
Helper = Callable[[Value], List[Value]]
A Helper takes a Value and returns a List of Values.
Now the assignment that errors:
def func_with_type(aa: bool) -> List[Value]:
return []
your_func2: Helper = func_with_type
func_with_type
only accepts a boolean, but you're assigning it to a type that should be able to accept an integer or string as well.
To see why that doesn't make sense, think about the following consumer of a Helper
function:
def consumer(func: Helper) -> List[Value]:
return func("Hello, world!")
A Helper
can take a Value
, which can either be bool
, int
or str
, so this usage should be fine. But func_with_type
only accepts a bool
, so cannot be called in this way, therefore we can't consider it a Helper
.
What I am actually doing is building a dispatch dict that has a key of the actual class (say bool, int, or str) and a value of a function that handles it. The return is a list of Value (eg, bool, int, or str).
Possibly what you want is a generic function, where the generic type is constrained by the union:
T = TypeVar('T', bool, int, str)
Helper = Callable[[T], List[T]]