You fail to consider subclasses:
class B(A):
def __bool__(self) -> bool:
return False
reveal_type(foobar(B())) # `int | None` at type checking time,
# but `B` at runtime.
To avoid this pitfall, mark A as @final:
from typing import final
@final
class A: ...
As for a better way to write optional_obj and optional_obj.attribute, see
How do I get Pylance to ignore the possibility of None?.