I have a type var that represents a child of specific interface
BuildableChild = TypeVar("BuildableChild", bound=Buildable)
The content of Buildable
does not really matters, let's assume it is just
class Buildable: ...
Now I want to have a function, that accepts a class of this type (i.e. a child class) and an optional filter function, which also accepts a buildable class:
def do_work_on_buildable_class(
buildable: type[BuildableChild],
filter_fn: Callable[[type[BuildableChild]], bool] | None = None,
) -> list[type[BuildableChild]]:
pass
Since type[BuildableChild]
is reused multiple times, I thought I could make an alias for it to reduce the number of brackets that you need to read:
from collections.abc import Callable
from typing import TypeAlias, TypeVar
class Buildable: ...
BuildableChild = TypeVar("BuildableChild", bound=Buildable)
BuildableChildType: TypeAlias = type[BuildableChild]
def do_work_on_buildable_class(
buildable: BuildableChildType,
filter_fn: Callable[[BuildableChildType], bool] | None = None,
) -> list[BuildableChildType]:
pass
It seems correct to me, but mypy is raising the Missing type parameters for generic type "BuildableChildType"
error for these lines:
buildable: BuildableChildType,
filter_fn: Callable[[BuildableChildType], bool] | None = None,
) -> list[BuildableChildType]:
So it assumes that type[BuildableChild]
is generic, and I think it is technically correct, but how else I would write a type alias for a type of TypeVar?
I don't think it is a solution to use BuildableChildType[Any]
because it's kind of ruins the whole idea of using the alias.
I did also try to rewrite
BuildableChildType: TypeAlias = type[BuildableChild]
to
type BuildableChildType = type[BuildableChild]
but then mypy is raising All type parameters should be declared ("BuildableChild" not declared)
error for this line
There is a difference between the following:
BuildableChild = TypeVar("BuildableChild", bound=Buildable)
BuildableChildType: TypeAlias = type[BuildableChild]
This is a concrete generic type (like list
). If you go to the type definition of list
, you can see that it has a free type variable _T
:
...
_T = TypeVar("_T")
...
class list(MutableSequence[_T]):
...
If you need to use list
in a type expression, you'll have to fully parameterise it, otherwise mypy will emit errors (Missing type parameters for generic type ...
).
BuildableChildType = TypeVar("BuildableChildType", bound=type[Buildable])
I believe that this is what you're actually looking for - a free type variable which statically ensures that the argument to parameter buildable
, input to filter_fn
, and the return type of do_work_on_buildable_class
are related. See mypy Playground.
(1) and (2) mean different things, though, so you'll need to solve a concrete programming or static typing issue to choose between them, rather than your stated reason in the question:
I thought I could make an alias for it to reduce the number of brackets that you need to read