Type hint of generic function?

Viewed 713

Consider the following code:

from typing import List, TypeVar, Callable

_T = TypeVar('_T')

# A generic function that takes a string and a list of stuff and that returns one of the stuff
Prompter = Callable[[str, List[_T]], _T]

# A function that takes such a Prompter and do things with it
ActionDef = Callable[[Prompter[_T]], None]

# A register of all ActionDef's
ACTION_DEFS: List[ActionDef[_T]] = []

I get an error from pylance on List[ActionDef[_T]]:

Type variable "_T" has no meaning in this context

If I do List[ActionDef] instead, it also complains:

Expected type arguments for generic type alias "ActionDef"

Basically it wants me to do something like ACTION_DEFS: List[ActionDef[int]] = [] which defeats the whole point.

Question1: how to define write ACTION_DEFS typing declaration?

Question2 (where the title comes from): Is there a way to define Prompter in such way that I don't need to carry the [_T] along everywhere?

1 Answers

The first error you encountered is because using a type variable with a generic type creates a generic alias, not a concrete type. You must annotate variables with concrete types, hence the error.

The second error, I assume it's specific to pylance, because in mypy an unparameterized generic type is equivalent to substituting all type variables for Any. So the type List[ActionDef] is equivalent to List[ActionDef[Any]].


From what I understand, you actually want your ActionDef alias to match any function that takes a Prompter of any type, i.e. Prompter[Any]. In this case, you can define it as:

ActionDef = Callable[[Prompter[Any]], None]
# or, if you're using mypy:
# ActionDef = Callable[[Prompter], None]

# Now `ActionDef` is no longer generic.
ACTION_DEFS: List[ActionDef] = []
Related