from typing import *
def example(value: Mapping[Union[str, int], Union[str, int]]):
x: Mapping[str, int] = {
"a": 1,
"b": 2,
"c": 3
example(x) # <-- MyPy doesn't like this: Argument 1 to "example" has incompatible type "Mapping[str, int]"; expected "Mapping[Union[str, int], Union[str, int]]"mypy(error)
from typing import *
def example(value: Union[Mapping[str, Union[str, int]],
Mapping[int, Union[str, int]]]):
x: Mapping[str, int] = {
"a": 1,
"b": 2,
"c": 3
example(x)
Then mypy is happy. Version:
mypy==0.761
a: Union[Mapping[str, Union[str, int]],
Mapping[int, Union[str, int]]]
b: Union[str, int] = 20
c = a[b] < mypy reports two errors, written below
Invalid index type "Union[str, int]" for "Union[Mapping[str, Union[str, int]],
Mapping[int, Union[str, int]]]"; expected type "str" mypy(error)
Invalid index type "Union[str, int]" for "Union[Mapping[str, Union[str, int]],
Mapping[int, Union[str, int]]]"; expected type "int" mypy(error)
@JelleZijlstra, @hauntsaninja thank you for your replies! 🌞 I thought there was a good reason for this behavior.
I am closing this issue, since I see it was already discussed.
FWIW, I think I understood that Union
is not the right tool to do the think I had in mind, described in my example above. The right tool is to define generic types for keys and values!
from typing import *
A = TypeVar("A", str, int)
B = TypeVar("B", str, int)
def example2(value: Mapping[A, B]):
x: Mapping[str, int] = {
"a": 1,
"b": 2,
"c": 3
example2(x)
y: Mapping[str, str] = {
"a": "1",
"b": "2",
"c": "3"
example2(y)
And I understood this, because in C# it would be the same (Union
doesn't exist in C#, you have to use interfaces
to describe something like union). I often take C# as example because I know it, it's static, and clearly it is mature about generics.
A basic example would be:
using System;
using System.Collections.Generic;
using System.Linq;
namespace netconsole
class Program
// a function that accepts any kind of dictionary as input and returns
// a new dictionary of only strings
static Dictionary<string, string> Example<A, B>(Dictionary<A, B> dict)
=> dict.ToDictionary(key => key.ToString(), value => value.ToString());
static void Main(string[] args)
var x = new Dictionary<string, int>() {
{"a", 1},
{"b", 2},
{"c", 3}
var a = Example(x);