Description
What
I want a new protocol added to typing
or typing_extensions
, expressing the aspects of Mapping
that are covariant with regards to the key type. That is, the Mapping
type, but without the __getitem__
and get
methods.
Something along the lines of:
class CovariantMappingLike(Protocol[KT_co, VT_co]):
# A better name for this protocol might be needed
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def keys(self) -> KeysView[KT_co]: ...
def items(self) -> ItemsView[KT_co, VT_co]: ...
def values(self) -> ValuesView[VT_co]: ...
Why
Mapping
s are often, in practice, treated in ways that make them covariant with regards to key. A specific example is laid out in a comment of mine found here: python/typing#445 (comment)
The Mapping
type, however, cannot be covariant w. regards to key, as it also implements methods that don't allow for it (__getitem__
and get
) to be covariant.
This leaves me unable to express, in a simple and idiomatic way, that I intend to use a Mapping
in a way that respects covariance.
Being able to write:
def foo(mapping: CovariantMappingLike[Hashable, Hashable]) -> int:
...
would allow me to express what I'm after. It would allow me to express: "Give me a mapping, but I promise to not be looking up keys on it."
This, again, makes it possible to have narrower key types for my Mapping
objects, as I can pass a narrowly typed Mapping
to foo
, without casting:
my_map: Dict[Literal["foo", "bar", "baz"], str] = {}
# I want this to be fine
foo(my_mapping)
I was prompted by @srittau to create this issue in python/typing#445 (comment)