-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypedDict totality ignored when unpacked for function call #12754
Comments
We need to consider whether it's best to err on the side of safety (with the possibility of false positives) or practicality (with the possibility of false negatives). There's no right answer, but whatever decision we make should be applied consistently. Consider how mypy handles the unpack operator for iterables. def my_function(a: int, b, int):
...
def func(b: list[int]):
my_function(*b)
func([1]) This type checks without errors even though it generates an exception at runtime. So mypy chose the "practical" choice here rather than the "safe" choice. For consistency, it probably makes sense that it would do the same for unpacking of TypedDicts with fields that are not required. |
I think that TypedDicts are a bit different to lists in this case, as they are more configurable. TypeDicts can specify which keys must be supplied vs those that can be omitted, whereas there is no way that I am aware of to specify a list that must always be a specified length. This is how ensure that from typing import TypedDict
def my_function(foo: int, bar: int = 2) -> None:
pass
class _MyTypedDict(TypedDict, total=True):
foo: int
class MyTypedDict(_MyTypedDict, total=False):
bar: int
a: MyTypedDict = {'foo': 1}
b: MyTypedDict = {'foo': 1, 'bar': 4}
c: MyTypedDict = {'bar': 4} # mypy - error: Missing key "foo" for TypedDict "MyTypedDict"
my_function(**a)
my_function(**b) https://mypy-play.net/?mypy=0.931&python=3.11&flags=strict&gist=d884981b53cc85cc37b7203f0dffde7a I think this situation is closer how mypy is strict with from typing import TypedDict
def my_function(foo: int, bar: int) -> None:
pass
a: int = 1
b: int | None = None
my_function(a, b) # mypy - error: Argument 2 to "my_function" has incompatible type "Optional[int]"; expected "int" https://mypy-play.net/?mypy=0.931&python=3.11&flags=strict&gist=192069ebb39cf087175008d34b88b8a5 Maybe there could be a strict (safe) vs relaxed (practical) unpacking configuration, with strict not allowing the list to be unpacked to be used with a fixed number of parameters. |
Bug Report
When unpacking a typeddict for a function call, mypy doesn't seem to check the totality of the typeddict, and instead assumes the keys are all present.
https://mypy-play.net/?mypy=latest&python=3.10&flags=strict&gist=5444e1100000a8f1678fe9cbcfc23921
Expected Behavior
Mypy should not assume that keys are present when the TypedDict has
total=False
, and treat it as potentially having any combination of they keys present.Actual Behavior
Mypy allows this, but when executed it gives the following error:
#11753
The text was updated successfully, but these errors were encountered: