Skip to content

Type hint incorrect on TypedDict.update? #5254

@alicederyn

Description

@alicederyn

Describe the bug
The update type hint on TypedDicts seems to declare the incoming parameter as a Partial of the same type, which permits illegal operations on subclasses. It should be a @final Partial (ideally with ReadOnly keys to support the new ReadOnly special form)

(I am deducing current behaviour from error messages, as I can't find it documented, so apologies for any mistakes here.)

To Reproduce
Run pyright on the code below

Expected behavior
The line a1.update(a2) should emit an error.

Screenshots or Code

# pyright: strict

from typing import TypedDict

class A(TypedDict):
    foo: int

class B(A, TypedDict):
    bar: str

class C(A, TypedDict):
    bar: int

def update_a(a1: A, a2: A) -> None:
    a1.update(a2)  # This should be an error

b: B = {"foo": 1, "bar": "baz"}
c: C = {"foo": 2, "bar": 3}
update_a(b, c)  #  b is no longer a B.

VS Code extension or command-line
pyright 1.1.313, on the command-line

Additional context
I first raised this here — https://discuss.python.org/t/pep-705-typedmapping/24827/24 — but the issue was masked by pyright's ignoring the type declaration on a2; with the introduction of a function wrapping the update call, the error is exhibited.

I believe the correct type hint for the update parameter is a final, non-total, readonly version of the original typeddict, i.e. in this case

from typing import final, TypedDict
from typing_extensions import ReadOnly

@final
class A_Update(TypedDict, total=false):
    foo: ReadOnly[int]

The final here is how we currently indicate that no extra keys can be present on the dictionary. Any ReadOnly keys in the original type should be dropped, as they cannot be modified.

This will likely break a lot of existing code though. At the moment, if I try to use a final-decorated type hint on update_a, I get an error like "X" is incompatible with "Partial[A]" because of a @final mismatch, which means anyone using the (I believe) correct type hinting would currently be getting an error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions