`TypedMapping` for extended compatibility?
Hello,
Consider the following, where lock aims at making provided argument immutable.
@dataclass
class Works:
foo: Mapping
def lock(self) -> None:
self.foo = MappingProxyType(self.foo)
It works great with mypy, no issue. Now imagine I want to enforce a bit more to foo by requesting it be compatible with a Movie. I would try the following, without success.
class Movie(TypedDict):
author: str
year: int
@dataclass
class Fails:
foo: Movie
def lock(self) -> None:
self.foo = MappingProxyType(self.foo) # error: Incompatible types in assignment (expression has type "MappingProxyType[str, object]", variable has type "Movie") [assignment]
Is there an workaround? If not, is if a good idea to discuss the possibility of a TypedMapping, that would simply work as follow?
class Movie(TypedMapping): # New feature ?
author: str
year: int
@dataclass
class Fixed:
foo: Movie
def lock(self) -> None:
self.foo = MappingProxyType(self.foo) # Would work
Thanks for your time.
All the best! Élie.
I found a few references mentioning this, most notably PEP 705 and a few related posts on the python forum:
- https://discuss.python.org/t/pep-705-typedmapping/24827
- https://discuss.python.org/t/introduce-a-typedmapping-analog-to-typeddict-but-frozen/51905
One of the mentioned issue was the lack of "strong use-case", which is a bit hard to discuss in complete objectivity and time-consistency. I personally find the use case I described in opening quite standard.
A point I'd like to make is that many discuss TypedMapping as a "read-only TypedDict", which seems incorrect to me, as it misses the distinction between Mapping and MappingProxyType. I think describing TypedMapping as a base of TypedDict would be more appropriate.
Yeah that was how I thought about it originally. I would have liked it to type data frames and other mapping like things.
With enum.Enum you can do something like
class DoubleThink(int, Enum):
FIVE = 2 + 2
So how about using this same trick to avoid having to introduce a new typing member, and instead extend TypedDict so that you can do e.g.
class Movie(Mapping[str, str | int], TypedDict):
author: str
year: int
I'm not sure if this has been proposed before, but I thought I might as well throw it out there.
I'm not entirely sure, but I think your approach forces inheritance from TypedDict which seems counterproductive (TypedMapping should be looser, am I right?)