Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Mypy errors in Generic class

I slightly modified the documented mypy generic example but got an error:

from typing import Generic, TypeVar, Union

T = TypeVar("T", bound=Union[int, float])

class Person(Generic[T]):

    def __init__(self, salary: T) -> None:
        self.salary: T = salary

    def get_yearly_bonus(self, amount: T) -> None:
        self.salary += amount

    def __str__(self) -> str:
        return f"Person(salary={self.salary})"

p = Person[int](9)
p.get_yearly_bonus(6)
print(p)

It seems mypy fails to recognize the fact that self.salary and amount must
be of the same type.

$ mypy test.py 
test.py:11: error: Incompatible types in assignment (expression has type "float", variable has type "T")
test.py:11: error: Unsupported operand types for + (likely involving Union)
Found 2 errors in 1 file (checked 1 source file)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem isn’t mypy failing to recognize that self.salary and amount share a type. mypy knows they both have type T, whatever T is.

The problem is that T isn’t guaranteed to be either int or float. T can be any subtype of Union[int, float]. It could be int, or float, or any subclass of those classes, like bool, or it could even be Union[int, float]!

For a sum of two objects of type T, mypy cannot assume the sum has type T. The most specific type mypy can deduce for the sum (accounting for mypy’s weird special case that treats int as a subtype of float) is float, which isn’t assignable to self.salary.

If you wanted T to be either int or float, a union bound isn’t the way to do that. The syntax for "either int or float" is

T = TypeVar('T', int, float)

With T specified this way, mypy can type-check Person against both possible types and see that the class is valid both ways.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading