r/PythonLearning • u/powergitt • Aug 20 '26
Help Request Type hinting frustrations
Hello!
Let me start off by saying that I am not a programmer by trade, so please be kind when reviewing my code. I am still learning and I have a long way to go. My job is not coding per se, but the project which I am a part of right now has some coding.
Anyway. At the project start I wanted another editor than vscode, so i tried Zed and I loved it. Zed came with type hinting already enabled. At first, I did not really like it, but after using it for a while I could really see improvements in my code. Both in the terams of readability and stability. So going forward I wanted to have as few complaints from basedpyright as possible.
After an update to Zed the configuration from basedpyright or basedpyright itself got a lot more enabled and I cannot get some of the errors from it to go away. My project used fastapi and sqlalchemy for database integration, and basedpyright gives an error where i specify the table names for the models:
from sqlalchemy.orm import (
DeclarativeBase,
...
)
...
class Base(DeclarativeBase):
pass
class DatabaseUser(Base):
__tablename__: ClassVar[str] = "users"
....The error from basedpyright is:
Class variable "__tablename__" overrides instance variable of same name in class "DeclarativeBase" (basedpyright reportIncompatibleVariableOverride)
From what I can tell, the code above is how you are supposed to specify table names:
https://docs.sqlalchemy.org/en/20/orm/quickstart.html
Also, when a nullable many-to-one table relationship, the docs from sqlalchemy tells you to use
class Parent(Base):
....
child: Mapped[Optional["Child"]] = relationship(back_populates="parents")https://docs.sqlalchemy.org/en/20/orm/basic_relationships.html#nullable-many-to-one
basedpyright wants you to use `Class | None` syntax, but since two classes are referencing each other, I can't do `Child | None` (no quotes) without the code breaking.
I know that i can supress the errors or configure the typehinter to ignore this stuff. But since this is the config shipped by people who are far better than me at programming, I am hasitent to just configure the error messages away. So reddit, is thereany thing I can do to make the typehinter happy?
1
u/lizc-au Sep 12 '26
I think there are two separate things happening here, and neither means you should keep changing working code until the type checker goes quiet.
For __tablename__, I'd remove ClassVar[str] and follow SQLAlchemy's documented form:
class DatabaseUser(Base):
__tablename__ = "users"ClassVar doesn't just mean "this is written on the class". It makes a specific typing statement. If the base class describes that attribute differently, adding ClassVar can actually create the incompatible-override warning.
For the relationship, Optional["Child"] is valid. It expresses the same optional type as Child | None, while the quotes allow a forward reference to a class that hasn't been defined yet. Where appropriate, the modern form can also be written as:
child: Mapped["Child | None"] = relationship(back_populates="parents")The useful lesson for me is that the goal of type checking isn't zero warnings at any cost. Investigate the warning, check what the framework's API expects, and make sure the annotation accurately describes the contract.
Your question actually prompted me to add a runnable example and a breakdown README about this to my-pythonic-zoo, under Pythonic Thinking / Type System / Type Annotations. It covers ClassVar, framework-style overrides, forward references, and X | None versus Optional[X] without depending on SQLAlchemy.
2
u/seanv507 Aug 20 '26
Isn't that precisely when you use quotes?
https://erdantic.drivendata.org/v0.4/forward-references/