I have the following two classes:
class MessageBase:
pass
class MessageChild(MessageBase):
pass
And the following function:
def action(message: MessageChild):
pass
Why does the following type hint for the given get_action
function produces an error in Pylance? Normally type hints using base classes are compatible with child classes.
def get_action() -> Callable[[MessageBase], None]:
return action
Expression of type "(message: MessageChild) -> None" cannot be assigned to return type "(MessageBase) -> None"
Type "(message: MessageChild) -> None" cannot be assigned to type "(MessageBase) -> None"
Parameter 1: type "MessageBase" cannot be assigned to type "MessageChild"
"MessageBase" is incompatible with "MessageChild"
If you flesh out your example a bit, you see why you get this warning:
class MessageChild(MessageBase):
def method_only_child_has(self):
pass
def action(message: MessageChild):
message.method_only_child_has()
We've added something to MessageChild
which does not exist in MessageBase
. action
expects a MessageChild
and can thus rely on that special something to be there.
Now:
the_action = get_action()
the_action(MessageBase())
According to the type annotation on get_action
, this is supposed to work. the_action
supposedly expects an argument of type MessageBase
, which we're providing here as requested. When you actually execute this code though, you'll get an AttributeError
, since method_only_child_has
does not in fact exist on MessageBase
.
That's the type error it's warning you about. It's not about an insufficient type annotation, it's correctly warning you about an actual potential error case.