It’s not clear in PEP 695 whether private members of a class should be taken into account when variance of the class’s type-vars gets inferred. Pyright’s current implementation (v1.1.336) are using them all, but I personally think that they need to be excluded. What will be your thoughts?
For example –
class Translator[K, V]: __dictionary: dict[K, V] def __init__(self, dictionary: dict[K, V], /) -> None: self.__dictionary = dictionary def __getitem__(self, key: K, /) -> V: return self.__dictionary[key]
I imagined that
K would be contravariant and
V would be covariant, because
K is only used as input and
V is only used as output. But in fact,
V are both inferred as invariant, because
__dictionary is typed as
dict[K, V] and both arguments of
dict are invariant.
What’s worse, even after re-typing
from collections.abc import Mapping class Translator[K, V]: __dictionary: Mapping[K, V] def __init__(self, dictionary: Mapping[K, V], /) -> None: self.__dictionary = dictionary def __getitem__(self, key: K, /) -> V: return self.__dictionary[key]
K is still inferred as invariant instead of contravariant, because there are methods like
collections.abc.Mapping which return the key type and make it invariant.
To make this sample work as I expected, I need to add a custom protocol, with only
__getitem__ method which I’m going to use, to further restrict the type of
__dictionary. But I don’t think that should be required.