I'm trying to figure out a nice way of doing type hints for a decorator. Here's a simplified/minimal example. The decorator is called @stringify_input and it converts the inputs of the decorated function to strings:
@stringify_input
def two_things(x: str) -> float:
return float(x + x)
assert two_things(1) == 11.0
# implementation with no hints:
def stringify_input(fn):
def inner(thing: int):
return fn(str(thing))
return inner
Say I don't know in advance what the decorated function returns, but I know my decorator doesn't change it. currently the undecorated functon returns a float, so the decorated one should too. I've figured out how to do that with TypeVar:
# types check
T = TypeVar("T")
def stringify_input(fn: Callable[[str], T]) -> Callable[[int], T]:
def inner(thing: int) -> T:
return fn(str(thing))
return inner
here's my question: those Callable[....] hints are hard to read, they'd be easier to understand if they had names (my IRL decorators are more complex). so i try this:
StringFn = Callable[[str], T]
IntFn = Callable[[int], T]
def stringify_input(fn: StringFn) -> IntFn:
def inner(thing: int) -> T:
return fn(str(thing)) # Returning Any from function declared to return 'T'
return inner
but that doesn't type check:
Returning Any from function declared to return 'T'
why is mypy unhappy with that? i literally just extracted the two expressions! something about how TypeVar works?