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, thereforeSelfannotation is invalid.To get rid of errors, you can either:
a) make sure it's always
self.__class__returned, which IS actualSelfb) type with what you are actually returning,
FancyCat