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
Set TypedDicts to always be their declared type as opposed to the type inferred when instantiated (2) (#3099)
[This was implemented originally by @rowillia in #2621. This PR includes
a few test updates.]
* Allow fields on a TypedDict to be subtypes of their declared types.
TypedDicts appear to have explicitly decided not to accept subtypes on fields,
but this behavior is counter intuitive. This made it so TypedDicts didn't
respect `Any` and caused problems with what should have been ducktype
compatible. This also brings TypedDicts more in line with other container
types and with how fields on classes behave.
```python
from typing import Dict
def foo() -> Dict[float, object]:
return {
1: 32
}
```
This fixes#2610
* Take suggestion from Jukka to have calls to typed dicts always result in exact declared type
See #2621 (comment)
return p # E: Incompatible return value type (got "Point", expected Mapping[str, str])
287
287
[builtins fixtures/dict.pyi]
288
288
289
+
[case testTypedDictAcceptsIntForFloatDuckTypes]
290
+
from mypy_extensions import TypedDict
291
+
from typing import Any, Mapping
292
+
Point = TypedDict('Point', {'x': float, 'y': float})
293
+
def create_point() -> Point:
294
+
return Point(x=1, y=2)
295
+
reveal_type(Point(x=1, y=2)) # E: Revealed type is 'TypedDict(x=builtins.float, y=builtins.float, _fallback=typing.Mapping[builtins.str, builtins.float])'
296
+
[builtins fixtures/dict.pyi]
297
+
298
+
[case testTypedDictDoesNotAcceptsFloatForInt]
299
+
from mypy_extensions import TypedDict
300
+
from typing import Any, Mapping
301
+
Point = TypedDict('Point', {'x': int, 'y': int})
302
+
def create_point() -> Point:
303
+
return Point(x=1.2, y=2.5)
304
+
[out]
305
+
main:5: error: Incompatible types (expression has type "float", TypedDict item "x" has type "int")
306
+
main:5: error: Incompatible types (expression has type "float", TypedDict item "y" has type "int")
307
+
[builtins fixtures/dict.pyi]
308
+
309
+
[case testTypedDictAcceptsAnyType]
310
+
from mypy_extensions import TypedDict
311
+
from typing import Any, Mapping
312
+
Point = TypedDict('Point', {'x': float, 'y': float})
313
+
def create_point(something: Any) -> Point:
314
+
return Point({
315
+
'x': something.x,
316
+
'y': something.y
317
+
})
318
+
[builtins fixtures/dict.pyi]
319
+
320
+
[case testTypedDictValueTypeContext]
321
+
from mypy_extensions import TypedDict
322
+
from typing import List
323
+
D = TypedDict('D', {'x': List[int]})
324
+
reveal_type(D(x=[])) # E: Revealed type is 'TypedDict(x=builtins.list[builtins.int], _fallback=typing.Mapping[builtins.str, builtins.list[builtins.int]])'
325
+
[builtins fixtures/dict.pyi]
326
+
289
327
-- TODO: Fix mypy stubs so that the following passes in the test suite
reveal_type(c1) # E: Revealed type is 'TypedDict(value=builtins.int, meta=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])'
345
-
reveal_type(c2) # E: Revealed type is 'TypedDict(value=builtins.int, meta=builtins.str, _fallback=typing.Mapping[builtins.str, builtins.object])'
346
-
reveal_type(joined_cells) # E: Revealed type is 'builtins.list[TypedDict(value=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.int])]'
382
+
reveal_type(c1) # E: Revealed type is 'TypedDict(value=builtins.object, meta=builtins.int, _fallback=typing.Mapping[builtins.str, builtins.object])'
383
+
reveal_type(c2) # E: Revealed type is 'TypedDict(value=builtins.object, meta=builtins.object, _fallback=typing.Mapping[builtins.str, builtins.object])'
384
+
reveal_type(joined_cells) # E: Revealed type is 'builtins.list[TypedDict(value=builtins.object, _fallback=typing.Mapping[builtins.str, builtins.object])]'
0 commit comments