I'm working in a pet project of mine and found this little issue. I want to use typings withtin a base class, the problem is that the return type of the class methods are defined by a field set by the subclasses. Here is my base class
class BaseRepository(metaclass=RequiredAttributes('model')):
model = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id) -> ??:
# return an object of the type defined in mode
...
class UserRepo(BaseRepository): # subclass
model = User # class type
...
I want to set the typing for the get
function to be the same object type as defined in the model field.
Any suggestion on how can I acomplish something like that?
Without the metaclass, this passes MyPy , which is correctly able to infer that x
is of type User
. I wasn't able to test it with the metaclass, as I don't have your metaclass definition. The solution uses a parameterised Generic
as a base class, which allows you to then assert to the type-checker that different methods across the class will have the same parameter and return argument types. A similar technique is used in Django's stub files .
NB You'll have to import Type
from the typing
module and use Optional[Type[M]]
instead of Optional[type[M]]
for your model
annotation if you're using Python <= 3.8.
from typing import Optional, Generic, TypeVar
M = TypeVar('M')
class BaseRepository(Generic[M], metaclass=RequiredAttributes('model')):
model: Optional[type[M]] = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id: int) -> M: ...
# return an object of the type defined in mode
class User:
pass
class UserRepo(BaseRepository[User]): # subclass
model = User # class type
x = UserRepo().get(1)
reveal_type(x) # Revealed type is "__main__.User*"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.