Here's a minimal example I've written:
from __future__ import annotations
from typing import Protocol
from typing_extensions import Self
class Cat(Protocol):
def add(self, other: Self) -> Self:
...
def sub(self, other: Self) -> Self:
...
class FancyCat(Cat):
def __init__(self, value: int):
self._value = value
def add(self, other: Self) -> Self:
return FancyCat(self._value + other._value)
def sub(self, other: Self) -> Self:
return FancyCat(self._value - other._value)
fc = FancyCat(3)
fc2 = FancyCat(4)
fc.add(fc2)
If I try to type check it, I get
$ mypy t.py
t.py:19: error: Incompatible return value type (got "FancyCat", expected "Self") [return-value]
t.py:22: error: Incompatible return value type (got "FancyCat", expected "Self") [return-value]
Found 2 errors in 1 file (checked 1 source file)
I'm so confused - isn't Self
FancyCat
in this case?
How can I satisfy mypy
here?
Your code does not guarantee that Self will be returned. For example, child classes will still return FancyCat
, therefore Self
annotation is invalid.
To get rid of errors, you can either:
a) make sure it's always self.__class__
returned, which IS actual Self
def add(self, other: Self) -> Self:
return self.__class__(self._value + other._value)
b) type with what you are actually returning, FancyCat
def sub(self, other: Self) -> FancyCat:
return FancyCat(self._value - other._value)