Both in my personal projects and at two of my workplaces I have found a specific case that python typehints cannot handle well enough.
from abc import abstractmethod, ABC
class A(ABC):
def process_child_method(self):
child_return = self.child_method()
# Some actions on the return of the method
...
return child_return
@abstractmethod
def child_method(self):
pass
class B(A):
def child_method(self) -> int:
return 83
b = B()
b.process_child_method() # None, according to pyright
The only way to handle it right now is to use Generics but that creates a weird decoupling in terms of typehints:
from typing import Generic, TypeVar
from abc import abstractmethod, ABC
T = TypeVar("T")
class A(ABC, Generic[T]):
def process_child_method(self) -> T:
child_return = self.child_method()
# Some actions on the return of the method
...
return child_return
@abstractmethod
def child_method(self) -> T:
pass
class B(A[int]):
def child_method(self) -> int:
return 83
b = B()
b.process_child_method() # int
which could easily lead to typehints lying in large classes where we are not careful such as:
class C(A[int]):
# Many lines of code here
...
def child_method(self) -> str:
return "83"
My examples are a bit esoteric and I do not necessarily consider this to be a good pattern but I believe we should have some way of describing “returns the same object as another method in the class”.
Let’s discuss it. I guess this introduces dependencies into typehints which could become rather buggy and hard to manage but maybe we can figure out some nice way of handling such cases. Something like a DependencyVariable or even just adding support for such cases into TypeVar.
I also understand that this is mostly the business of the tool creators but the original peps for typing also haven’t covered this use case.