Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't dict[str, str] assignable to Mapping[str | int, str] (Mapping key type isn't covariant)?

Given this code:

from collections.abc import Mapping

def my_fn(m: Mapping[str | int, str]):
    print(m)

d = {"a": "b"}
my_fn(d)

both mypy 1.16.0 and pyright 1.1.400 report that it is invalid to assign d to the argument m. For example pyright outputs:

error: Argument of type "dict[str, str]" cannot be assigned to parameter "m" of type "Mapping[str | int, str]" in function "my_fn"
    "dict[str, str]" is not assignable to "Mapping[str | int, str]"
      Type parameter "_KT@Mapping" is invariant, but "str" is not the same as "str | int" (reportArgumentType)

Why is this the case? I understand why assigning dict[str, str] to a MutableMapping[str | int, str] would be bad (the callee could insert int keys into the dict), but Mapping is immutable.

like image 949
Kerrick Staley Avatar asked Sep 01 '25 04:09

Kerrick Staley


1 Answers

Making the Mapping keys covariant has been proposed (twice) and rejected.

There's not much you can do besides declare the type of d manually.

from collections.abc import Mapping

def my_fn(m: Mapping[str | int, str]):
    print(m)

d: dict[str | int, str] = {"a": "b"}
my_fn(d)
like image 184
Anerdw Avatar answered Sep 02 '25 19:09

Anerdw