4
def function(a: int, b: str) -> None:
    pass 

def wrapper(extra: int, *args, **kwargs) -> None:
    do_something_with_extra(extra)
    function(*args, **kwargs)

Is there an easy way for wrapper to inherit function()'s type hints without retyping all of them? Normally I'd write

def wrapper(extra: int, a: int, b: str) -> None:

But it becomes very verbose with a lot of arguments, and I have to update wrapper() every time I update function()'s arguments, and using *args, **kwargs means there won't be proper autocomplete in vscode and other editors.

Some Guy
  • 576
  • 1
  • 4
  • 17

1 Answers1

4

The best that you can do is to use a decorator for this purpose, and you can use Concatenate and ParamSpec. I use python 3.8 and I had to install typing_extensions for them. In the code below, if you type function in VSCode, it will show the int argument but without the "extra" name in front of it.

from typing import Callable, TypeVar
from typing_extensions import Concatenate, ParamSpec


P = ParamSpec('P')
R = TypeVar('R')

def wrapper(func: Callable[P, R]) -> Callable[Concatenate[int, P], R]:
    def inner(extra, *args, **kwargs):
        print(extra)
        func(*args, **kwargs)
    
    return inner

@wrapper
def function(a: int, b: str) -> None:
    print(a, b)
    pass 

# typing function will show 'function: (int, a: int, b: str) -> None'
  • 3
    This is not what I'm asking, note that I'm not using a decorator. I'm simply calling the function from inside the wrapper. It could also be a closure, so a decorator there would not be an option. – Some Guy Feb 08 '22 at 16:33