I had trouble figuring out how to phrase my question, but I have code like the following:
- There's a generic class (
BaseOuter) with a method (to_inner) whose return type is generic. - There are concrete subclasses of that generic class (e.g.
Outer). When I callOuter().to_inner(), the inferred return type isInneras I expect. - I create a generic function that takes an optional
BaseOuterand callsto_inner()on it. But when I pass anOuterto this function, the inferred return type isBaseInner, and notInneras I expected.
Am I doing something wrong? Is there a way to make type checkers realize that to_inner(Outer()) returns an Inner?
import typing
class BaseInner:
pass
T_co = typing.TypeVar('T_co', bound=BaseInner, covariant=True)
T = typing.TypeVar('T', bound=BaseInner)
class BaseOuter(typing.Generic[T_co]):
def to_inner(self) -> T_co:
return self.InnerType()
@typing.overload
def to_inner(outer: BaseOuter[T]) -> T: ...
@typing.overload
def to_inner(outer: None) -> None: ...
def to_inner(outer: typing.Optional[BaseOuter[T]]) -> typing.Optional[T]:
return outer.to_inner() if outer else None
class Inner(BaseInner):
pass
class Outer(BaseOuter[Inner]):
InnerType = Inner
this_is_an_Inner = Outer().to_inner()
unfortunately_a_BaseInner = to_inner(Outer())