Skip to content

Possible false positive calling dict.update() method with TypedDict hierarchy #9335

Closed
@james-perretta

Description

@james-perretta

Python version: 3.8.2
mypy version: 0.782
mypy flags: --strict (same result without this flag)

I've encountered what looks like a false positive when calling .update() on TypedDicts that have some required and some optional fields. I have a hierarchy of TypedDicts with some required fields in the base class and some optional fields in the derived class. Here is a minimal snippet that reproduces the error:

from typing import TypedDict


class Base(TypedDict):
    id: int


class Derived(Base, total=False):
    description: str


update_me: Derived = {
    'id': 1,
    'description': 'norsetanrst'
}

new_data: Derived = {
    'id': 2
}
# "incompatible type" error from mypy
update_me.update(new_data)

I expected this to type check with no errors. However, mypy emits the following about the last line:

$ mypy --strict
demo.py:21: error: Argument 1 to "update" of "TypedDict" has incompatible type "Derived"; expected "TypedDict({'content'?: Dict[str, int], 'description'?: str})"
Found 1 error in 1 file (checked 1 source file)

It seems like mypy is expecting a TypedDict with the same fields (but all optional) as Derived. If I change the last line to update_me.update(update_me), the same error occurs. If I add total=False to Base's signature, the error goes away, but then I no longer have any required fields.

Also interesting to note: reveal_type(update_me.update) prints the signature I would expect:

note: Revealed type is 'def (TypedDict('wee.Derived', {'id': builtins.int, 'description'?: builtins.str}))'

And if I inline the argument, i.e. update_me.update({'id': 2}), the error goes away. However, my use case is
such that doing so is not a viable solution.

Thank you! Please let me know if there's anything I've missed.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions