Was reading PEP483 and there was this complex example at the end about creating a class when Base
class instances behave contravariantly but it’s subclass instances (Derived
) behavee covariantly. That a real monster
A type checker finds from the second declaration that Derived[Manager] is a subtype of Derived[Employee], and Derived[t1] is a subtype of Base[t1]. If we denote the is-subtype-of relationship with <, then the full diagram of subtyping for this case will be:
Base[Manager] > Base[Employee] v v Derived[Manager] < Derived[Employee]
so that a type checker will also find that, e.g., Derived[Manager] is a subtype of Base[Employee].
Is this a real thing and something like this could occur in real life cases?
Though typing for this example does work as described above (at least in Pyright), Pyright and Mypy still prohibit overwriting contravariant generic type parameter in subclass with covariant parameter (and vice versa).
Is this something that’s prohibited / allowed in the spec or it’s unspecified?
from typing import TypeVar, Generic
class Employee: ...
class Manager(Employee): ...
T_co = TypeVar("T_co", Employee, Manager, covariant=True)
T_contra = TypeVar("T_contra", Employee, Manager, contravariant=True)
class Base(Generic[T_contra]): ...
# Type "T_co@Derived" cannot be assigned to type variable "T_contra@Base"
# Variance of type argument "T_co@Derived" is incompatible with base class "Base"
class Derived(Base[T_co]): ...