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.
Describe the bug
The
updatetype 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@finalPartial (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
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
The
finalhere is how we currently indicate that no extra keys can be present on the dictionary. AnyReadOnlykeys 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.