I have a system where i want to store a function along with its arguments for later invocation. I have tried:
import typing
P = typing.ParamSpec("P")
class JobPayload(typing.NamedTuple):
fn: typing.Callable[P, None]
args: P.args
kwargs: P.kwargs
but the types of args and kwargs is not accepted. How do I type this correctly?
Your code is invalid:
[
P.args
andP.kwargs
] can only be used as the annotated types for*args
and**kwargs
, accessed from aParamSpec
already in scope.— Generics § The components of a
ParamSpec
/ Valid use locations | Python typing specification
As noted by @wjandrea, Mypy doesn't point out any problems. This is due to a known bug, however.
The best you can do is to use a TypeVarTuple
to represent the type of the parameters. The downsides are that their names are lost, and you can't have keyword-only arguments.
from collections.abc import Callable
from typing import NamedTuple
class JobPayload[*Ts](NamedTuple):
fn: Callable[[*Ts], None]
args: tuple[*Ts]
def f(a: int, /, b: str, c: float) -> None: ...
payload = JobPayload(f, (42, 'lorem')) # error