Escaping Contravariance Hell
Briefly

Contravariance refers to the relationship between types in Python, particularly with type checkers like mypy or Pyright. An example illustrates how assigning a more specific function type to a more general function type can lead to errors. Specifically, assigning Callable[[Carrot], None] to Callable[[Vegetable], None] fails due to contravariance in parameters. This means that if a function is specific to a subtype, it cannot replace a function that operates on a supertype. Understanding contravariance is crucial for resolving type checker errors and avoiding confusion.
If you want a vegetable and I give you a carrot, you'll be happy. If you want a function which works on all vegetables and I give you a function which only works on carrots, you'll be disappointed.
The reason we can't assign Callable[[Carrot], None] to Callable[[Vegetable], None] is that Callable is contravariant in its parameters.
Callable[[B], ...] is a subtype of Callable[[A], ...], meaning we cannot derive functions in a way that makes them less general.
By the end, you'll no longer fear type checker error messages related to variance.
Read at Quansight
[
|
]