You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
from typing import TypedDict
def my_function(foo: int, bar: int, baz: str) -> None:
pass
class MyTypedDict(TypedDict, total=False):
foo: int
bar: int
baz: str
a: MyTypedDict = {'bar': 1}
my_function(**a) # Should be error here, as a doesn't contain foo or baz
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:
Traceback (most recent call last):
File "<path>\typeddict1.py", line 17, in <module>
my_function(**a) # Should be error here, as a doesn't contain foo or baz
TypeError: my_function() missing 2 required positional arguments: 'foo' and 'baz'
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.
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.
Zeckie
changed the title
TypedDict totatity ignored when unpacked for function call
TypedDict totality ignored when unpacked for function call
May 9, 2022
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 MyTypedDict always contains 'foo', but does not need to have a 'bar':
I think this situation is closer how mypy is strict with Optional (even to the point they can both be described with the word optional). If a variable could be None, it can't be used in a case that requires an int.
fromtypingimportTypedDictdefmy_function(foo: int, bar: int) ->None:
passa: int=1b: int|None=Nonemy_function(a, b) # mypy - error: Argument 2 to "my_function" has incompatible type "Optional[int]"; expected "int"
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: