Foo.__eq__ is being defined the name
Foo is still unbound, because the class itself hasn’t yet been created. Remember: function arguments are evaluated at function definition time, not at function call time.
From Python 3.7+ you can postpone evaluation of annotations by adding this import at the top of the module:
from __future__ import annotations
For Python < 3.7, you can use string literals to delay evaluation of the type:
class Foo: def __init__(self, key: str) -> None: self.key = key def __eq__(self, other: 'Foo') -> bool: return self.key == other.key print('should be true: ', Foo('abc') == Foo('abc')) print('should be false: ', Foo('abc') == Foo('def'))