Reputation: 361
I am trying to figure out how to get Python generic type-hinting to play nice with a constructor argument of Type[C]. Consider this code sample:
class Foo(object):
fooval: str
def __init__(self, val):
self.fooval = val
class Bar(object):
barval: str
def __init__(self, val):
self.barval = val
T = TypeVar('T', Foo, Bar)
class FooBarContainer(Generic[T]):
child: T
# Type[T] seems logical here, but that's not valid according to the docs
def __init__(self, ctorable: Type[Union[Foo, Bar]], val):
self.child = ctorable(val)
baz = FooBarContainer(Foo, val)
# This does not get flagged by type-checkers, but will obviously fail at runtime
failure = baz.child.barval
Attempting to use Type[T] results in a type-checker error:
Expected Type[T], got Type[Foo]
So the goal here is to figure out how to get TypeVars to work with the Type[C] from typing. This way static analysis would know that when I call a particular func with a particular Type[T], I am expecting to get T back. I can't seem to find any docs that would help me here.
The same issue arises when dealing with functions too. For example, this is valid syntax, but obviously not valid in terms of typing:
def initor(thing_type: Type[Union[Foo, Bar]], val) -> T:
return thing_type(val)
Upvotes: 2
Views: 1756
Reputation: 64308
Can you clarify what you mean by "Type[T] seems logical here, but that's not valid according to the docs"?
In particular, what docs are you looking at? The following code works as expected for me, using mypy 0.630:
class FooBarContainer(Generic[T]):
child: T
def __init__(self, ctorable: Type[T], val) -> None:
self.child = ctorable(val)
val = 3
baz = FooBarContainer(Foo, val)
# Mypy reports a `"Foo" has no attribute "barval"` error
failure = baz.child.barval
If the docs imply giving ctorable
a type of Type[T]
does not work, they should probably be updated.
Upvotes: 1