I’m trying to write a function that “cache” the parameters used to build some classes, and may be applied to different classes.
However I’m not sure hot to properly typecheck them. I tried to use the ParamSpec
and a class Protocol
to try to capture the required __init__
signature, but I think I’m missing something.
On mypy Playground you can find a mypy gist, and, at the end, I am unable to get a type checker error for a wrong usage of the function (witch is my goal)
(for reference this is the snippet)
from typing import Generic
from typing import ParamSpec
from typing import Protocol
from typing import reveal_type
P0 = ParamSpec('P0')
class T1(Generic[P0], Protocol):
def __init__(self, *args: P0.args, **kwargs: P0.kwargs) -> None: ...
class T2(Generic[P0], Protocol):
def __call__(self, cls: type[T1[P0]]) -> T1[P0]: ...
class C:
def __init__(self, foo: int, bar: str) -> None: ...
class D:
def __init__(self) -> None: ...
def factory_builder[**P](*args: P.args, **kwargs: P.kwargs) -> T2[P]:
def factory(cls: type[T1[P]]) -> T1[P]:
return cls(*args, **kwargs)
return factory
factory = factory_builder(1, bar='xxx')
reveal_type(factory)
c = factory(C) # ==> c == C(1, bar="xxx")
reveal_type(c)
d = factory(D) # error
reveal_type(d)