-
Notifications
You must be signed in to change notification settings - Fork 288
-
Trying to learn how to write statically typed Python, but got confused for quite some time. Here is a toy example:
from typing import TypedDict from collections.abc import Mapping # represent the loose idea of a point as a mapping (i.e. dict or variants) from coordinates to floats type PointLike = Mapping[str, float] # a specific type of point class Point2D(TypedDict): x: float y: float # other types of points may be defined here or elsewhere (thanks to duck typing) # examples: 3D space, RGB... # the point (pun intended) is to implement transformations between different point types # those should be abstracted with a Protocol later on # here is a trivial transformation def identity_transform[T: PointLike](p: T) -> T: # return the point unchanged return p # let's test it my_point = Point2D(x=0.7, y=-0.3) identity_transform(my_point) # runs fine, but type checker error!
Both mypy and pyright will error on the last line, as can be seen in the playground links provided.
My main question is: why is this? After thinking about it for way too long, my guess would be that, since Python dictionaries are mutable, there is nothing stopping you from adding another key of a different type to my_point. Therefore, type checkers cannot infer its type as Mapping[str, float], and are inferring the TypedDict instance to be like Mapping[str, Any]. Please correct me if I am wrong.
A second question is: what would, then, be the appropriate way to implement the idea in the problem while keeping static type checkers happy?
Beta Was this translation helpful? Give feedback.
All reactions
To understand why your TypedDict isn't assignable to Mapping[str, float], check out this section of the typing spec. (Scroll down to the last bullet point in that section.)
There is a draft PEP 728 that proposes to add the concept of "closed TypedDicts" to the type system. Pyright has experimental support for this PEP if you want to play around with it. Here's what that looks like in the pyright playground.
Replies: 1 comment 1 reply
-
To understand why your TypedDict isn't assignable to Mapping[str, float], check out this section of the typing spec. (Scroll down to the last bullet point in that section.)
There is a draft PEP 728 that proposes to add the concept of "closed TypedDicts" to the type system. Pyright has experimental support for this PEP if you want to play around with it. Here's what that looks like in the pyright playground.
Beta Was this translation helpful? Give feedback.
All reactions
-
This is it, thanks!
Beta Was this translation helpful? Give feedback.