Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve "Incompatible return value type (got "FancyCat", expected "Self")"

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?

like image 336
ignoring_gravity Avatar asked Oct 16 '25 21:10

ignoring_gravity


1 Answers

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) 
like image 131
matszwecja Avatar answered Oct 19 '25 12:10

matszwecja