["python","multiple-inheritance","mypy","python-typing"]
How do I correctly add type-hints to Mixin classes?

Consider the following example. The example is contrived but illustrates the point in a runnable example: class MultiplicatorMixin: def multiply(self, m: int) -> int: return self.value * m class AdditionMixin: def add(self, b: int) -> int: return self.value + b class MyClass(MultiplicatorMixin, AdditionMixin): def __init__(self, value: int) -> None: self.value = value instance = MyClass(10) print(instance.add(2)) print(instance.multiply(2)) When executed this will give the following output: 12 20 The code works. But running mypy on it, yields the following errors: example.py:4: error: "MultiplicatorMixin" has no attribute "value" example.py:10: error: "AdditionMixin" has no attribute "value" I understand why mypy gives this result. But the mixin classes are never used by themselves. They are always used as additional superclasses. For context, this is a pattern which has been used in an existing application and I am in the process of adding type-hints. And in this case, the errors are false-positives. I am thinking about rewriting the part using the mixins as I don't particularly like it and the same could probably be done with reorganising the class hierarchy. But I still would like to know how something like this could be properly hinted.
In addition to Campi's answer about the mypy's recommendation of typing mixins with Protocol: An alternative to typing the methods' selfs is just inheriting the protocol. from typing import Protocol class HasValueProtocol(Protocol): @property def value(self) -> int: ... class MultiplicationMixin(HasValueProtocol): def multiply(self, m: int) -> int: return self.value * m class AdditionMixin(HasValueProtocol): def add(self, b: int) -> int: return self.value + b class MyClass(MultiplicationMixin, AdditionMixin): def __init__(self, value: int) -> None: self.value = value Additionally, if you are TYPE_CHECKING a Protocol, and given that you cannot forward reference a parent class (i.e. passing the parent class as a string literal), a workaround would be: from typing import Protocol, TYPE_CHECKING if TYPE_CHECKING: class HasValueProtocol(Protocol): @property def value(self) -> int: ... else: class HasValueProtocol: ... class MultiplicationMixin(HasValueProtocol): def multiply(self, m: int) -> int: return self.value * m ...