Suppose I have function that takes type as argument and returns instance of that type:
def fun(t):
return t(42)
Then I can call it and get objects of provided types:
fun(int) # 42
fun(float) # 42.0
fun(complex) # (42+0j)
fun(str) # "42"
fun(MyCustomType) # something
That list is not exhaustive, I'd like to be able to use any type with appropriate constructor.
Then, I'd like to add type hints for that function. What should be the type hint for return value of that function?
I've tried using simply t
, as t
is a type:
def fun(t: type) -> t:
return t(42)
but that doesn't work:
main.py:1: error: Name 't' is not defined
This answer suggests using a TypeVar
:
from typing import TypeVar
T = TypeVar("T")
def fun(t: T) -> T:
return t(42)
But that doesn't seem to be right, as T
denotes a type, so it suggests that type itself is returned, not its instance. Mypy rejects it:
main.py:6: error: "object" not callable
Using Any
obviously work, but I feel it's too vague, it doesn't convey the intent:
from typing import Any
def fun(t: type) -> Any:
return t(42)
Best Answer
TLDR: You need a
TypeVar
for the return type of callingt
:Constraining on a type is too restrictive here. The function accepts any
Callable
that takes an integer, and the return type of the function is that of theCallable
. This can be specified using aTypeVar
for the return type:This works for types as well, because type instantiation is a call.
If a more complex signature, e.g. with keyword arguments, is needed, use
Protocol
(fromtyping
ortyping_extensions
).Note that if one explicitly wants to pass only
42
to theCallable
,Literal
(fromtyping
ortyping_extensions
) can be used to specify that.Note that any function of the type
Callable[[int], R]
also satisfiesCallable[[Literal[42]], R]
.