Intrastellar Explorer
Intrastellar Explorer

Reputation: 2381

Python type hint Callable with one known positional type and then *args and **kwargs

I the below function foo, which has:

from typing import Callable

def foo(bar: str, *args, **kwargs) -> None:
    """Some function with one positional arg and then *args and **kwargs."""

foo_: Callable[[str, ...], None] = foo  # error: Unexpected '...'

How can I type hint this?

Currently, mypy==0.812 throws the error: error: Unexpected '...' [misc]

Upvotes: 4

Views: 1628

Answers (2)

Josiah
Josiah

Reputation: 1364

I'd probably use Protocols for this. They're generally a bit more flexible than Callables. It would look something like this

from typing import Protocol

class BarFunc(Protocol):
    def __call__(fakeself, bar: str, *args, **kwargs) -> None:
        # fakeself gets swallowed by the class method binding logic
        # so this will match functions that have bar and the free arguments.
        ...

def foo(bar: str, *args, **kwargs) -> None:
    """Some function with one positional arg and then *args and **kwargs."""

foo_: BarFunc = foo

Upvotes: 5

Mario Ishac
Mario Ishac

Reputation: 5877

You can't do this right now like Samwise's comment says, but in Python 3.10 (under PEP 612: Parameter Specification Variables), you will be able to do this:

from typing import Callable, ParamSpec, Concatenate

P = ParamSpec("P")

def receive_foo(foo: Callable[Concatenate[str, P], None]):
    pass

I'm not sure if you'll be able to declare a TypeAlias for it though (because P cannot be used in global scope), so you may have to specify the type inline with P each time.

Upvotes: 5

Related Questions