I have an interface
class Moveable(Protocol):
position: Tuple[int, int]
I implement the interface with a class that happens to use a getter to imitate the attribute position: Tuple[int, int]
class Player:
_x: int
_y: int
@property
def position(self) -> Tuple[int, int]:
return (self._x, self._y)
I instantiate a Moveable
variable to Player()
, but Pylance raises an error
entity: Moveable = Player()
(class) Player()
Expression of type "Player" cannot be assigned to declared type "Moveable"
"Player" is incompatible with protocol "Moveable"
"position" is invariant because it is mutable
"position" is an incompatible type
"property" is incompatible with "Tuple[int, int]" PylancereportGeneralTypeIssues
The error goes away if I change the type annotation on the interface to property
class Moveable(Protocol):
position: property # fixes Pylance alert
This isn't tenable as I may have classes that do not use a getter to produce a position
but instead have it directly as an attribute.
I want my interface to be agnostic as to whether classes implement a position: Tuple[int, int]
member using a @property
or as a direct attribute.
A non-ideal attempt at a solution was to use a Union
, but that oddly isn't acceptable to Pylance either
class Moveable(Protocol):
position: Union[Tuple[int, int], property]
class) Player()
Expression of type "Player" cannot be assigned to declared type "Moveable"
"Player" is incompatible with protocol "Moveable"
"position" is invariant because it is mutable
"position" is an incompatible type
Type "property" cannot be assigned to type "Tuple[int, int] | property"
"property" is incompatible with "Tuple[int, int]" PylancereportGeneralTypeIssues
Seems like this should be supported. Is it? Anyway to achieve the effect?