[Python] type checking: assignment of merged dicts not compatible, even though individual...

Discussão em 'Python' iniciado por Stack, Maio 17, 2025.

  1. Stack

    Stack Membro Participativo

    I have a situation where I want to assign the union of two dicts (using |) to a typed dict variable. Each of the dicts on its own is assignment compatible, but assigning the result of the merge where at least one of the dicts is a literal results in MyPy and Pyright both reporting an error:

    from typing import Literal

    type MyType = Literal['a', 'b']


    def f() -> dict[MyType, str]:
    d1: dict[MyType, str] = {'a': 'foo'} # <-- no error
    d2: dict[MyType, str] = {'b': 'bar'} # <-- no error
    d3: dict[MyType, str] = d1 | d2 # <-- no error
    d4: dict[MyType, str] = {'a': 'foo'} | {'b': 'bar'} # <-- error "dict[str, str]" is not assignable to "dict[MyType, str]"
    d5: dict[MyType, str] = {'a': 'foo'} | d2 # <-- error "dict[str, str]" is not assignable to "dict[MyType, str]"

    return d4


    If type checkers can recognize that each of the dicts on its own is assignment compatible, why can they not recognize that the merge/union of two compatible dicts is assignment compatible?

    Update

    If I cast the keys as MyType, MyPy is happy, but Pyright still complains: i.e., {cast(MyType, 'a'): 'foo'} | {cast(MyType, 'b'): 'bar'} works for MyPy. And if I cast the whole union, that works for both: i.e. cast(dict[MyType, str], {'a': 'foo'} | {'b': 'bar'}). Seems like they should be able to figure it out, even without the cast, though.

    Continue reading...

Compartilhe esta Página