I want to statically enforce that a method of a class returns a value wrapped in some abstract type, that I know nothing about:
E.g. given the abstract class
F = ???
class ThingF(Generic[F]):
@abstractmethod
def action(self) -> F[Foo]:
...
I want to to be able to statically check that this is invalid:
class ThingI(ThingF[List]):
def action(self) -> Foo:
...
because action does not return List[Foo].
However the above declaration for ThingF does not even run, because Generic expects its arguments to be type variables and I cannot find a way to make F a type variable "with a hole".
Both
F = TypeVar('F')
and
T = TypeVar('T')
F = Generic[T]
do not work, because either TypeVar is not subscriptable or Generic[~T] cannot be used as a type variable.
Basically what I want is a "higher kinded type variable", an abstraction of a type constructor, if you will. I.e. something that says "F can be any type that takes another type to produce a concrete type".
Is there any way to express this with Python's type annotations and have it statically checked with mypy?