Edit: As noted in the comments by @PanagiotisKanavos, this method to interact with databases is redundant. Since the main question is about usage of Generics, I'll leave the question open. Original Text: I'm trying to write a generic class that acts as the Database Repository for a number of different SQLModel models. I have bound the _ModelType TypeVar to SQLModel hoping that it would remove all type warnings, but I still get warnings in when I return SQLModel types in methods that expect _ModelType. I also tried constraining the _ModelType to a SQLModel too, but it didn't make any difference. Here is the abstract repository definition. from sqlmodel import SQLModel import typing from sqlalchemy.engine.result import ScalarResult _ModelType = typing.TypeVar( "_ModelType", bound=SQLModel, ) class BaseRepository(typing.Generic[_ModelType]): def __init__(self, session: Session, model_class: typing.Type[SQLModel]): self.session = session self.__model_class = model_class # Static hinting works as expected def save(self, obj: _ModelType) -> _ModelType: """ Generic method to save an object to the database. """ self.session.add(obj) return obj def get_one(self, obj_id: typing.Any) -> typing.Optional[_ModelType]: obj = self.session.get(self.__model_class, obj_id) #SQLModel | None return obj # Warning: Type "SQLModel" is not assignable to type "_ModelType@BaseRepository" def query(self, *conditions: typing.Union[_ColumnExpressionArgument[bool], bool] ) -> ScalarResult[_ModelType]: stmt = select(self.__model_class) for c in conditions: stmt = stmt.where(c) return self.session.exec(stmt).all() #Similar warning along with: Type parameter "_T_co@Sequence" is covariant, #but "SQLModel" is not a subtype of "_ModelType@BaseRepository" and here is a basic example of usage (The actual implementation wraps the session creation, management, all repositories creation, and auto-commit on exit in a UnitOfWork context manager). from utils.db_new import engine from order_management.repository_new import BaseRepository from order_management.models import Order, Customer from sqlmodel import Session import logging logging.basicConfig(level=logging.INFO) order_repo = BaseRepository[Order](Session(engine), Order) all_orders = order_repo.query( Order.pickup_type == "pickup", Customer.name == "Diaa Malek", ) [print(o.id) for o in all_orders] order = order_repo.get_one(1088) if order: print(order.items) Functionality-wise, it works exactly as intended. Each return type is annotated correctly. I could also just type: ignore and move on with my life. But I'm still not sure I understand those warnings or how to avoid them. Am I misusing Generics in some way, or is this an anti-pattern or overcomplication that should not even exist? Also, is it possible to use _ModelType directly instead of passing the model_type in the Repository constructor? I realize it doesn't make any difference, but I wonder. References: Difference between TypeVar('T', A, B) and TypeVar('T', bound=Union[A, B]) Repository Design Pattern Continue reading...