I have code that looks like the following:
from typing import Callable
def decorate(func: Callable[[str], None]) -> Callable[[str], None]:
return func
@decorate
def do_something(some_str: str = 'Hello world') -> None:
print(some_str)
if __name__ == '__main__':
do_something()
When running mypy, it reports the following error for the last line:
error: Too few arguments for "do_something" [call-arg]
How can I fix this error (without changing the return type of decorate
to Callable[..., None]
)?
Use a TypeVar
to indicate that the input and return type are equivalent and defined by the Callable
received. Since Callable
types include the entire signature, this lets the type checker infer positional/optional/keyword arguments as well.
from typing import Callable, TypeVar
# A type variable that can represent any Callable type
C = TypeVar("C", bound=Callable)
# The input Callable type defines the output Callable type as well
def decorate(func: C) -> C:
return func
If decorate
can only work with callables that may take a string, adjust the bound
accordingly.
# A type variable that can represent any Callable type that takes a string
C = TypeVar("C", bound=Callable[[str], None])
Notably, a callable taking a str
or using a default still satisfies Callable[[str], None]
since it can be called with a str
argument.