El vie, 19 mar 2021 a las 12:42, Greg Werbin (<outthere@me.gregwerbin.com>) escribió:
Note: this was originally posted on the Discourse forum (https://discuss.python.org/t/7721), but it was recommended that I post here instead.

In PEP-589: “Inheritance”, it is stated:

> Changing a field type of a parent TypedDict class in a subclass is not allowed.

However, this restriction seems perhaps too restrictive in the presence of typing.Literal and PEP-586.

Consider a situation like the following, which might describe some polymorphic data returned from a web API:

    from typing import Literal, TypedDict

    # Assume these all have several other fields

    class BaseDatum(TypedDict):
        id: str
        datumType: str

    class Thing(BaseDatum):
        datumType: Literal["thing"]

    class Widget(BaseDatum):
        datumType: Literal["widget"]

This seems like a reasonable thing that someone might want to do, especially in a context where you can’t use something like Marshmallow for runtime validation & deserialization (don’t want performance overhead, restricted from using 3rd-party dependencies, etc).

However, in the above example, MyPy emits:

> tmp1.py:10: error: Overwriting TypedDict field "datumType" while extending
> tmp1.py:13: error: Overwriting TypedDict field "datumType" while extending
> Found 2 errors in 1 file (checked 1 source file)

Typically, Literal["widget"] is considered a subclass of str, as in:

    from typing import Literal
    x: Literal["hello"] = "hello"
    y: str = x

It appears that the MyPy devs faithfully honored the restriction on changing type that is stated in PEP-589, but I think in this specific case the restriction is excessive.

Should there be a revision to the TypedDict specification to allow this particular case? For that matter, why shouldn’t TypedDict members be covariant in general? Or is there a good reason why the restriction is what it is?

Changing the type in a child is unsafe because TypedDicts are mutable:

def f(datum: BaseDatum):
    datum["datumType"] = "some string"

w: Widget
f(w)
assert w["datumType"] == "widget"  # boom

We could get around that if we had a notion of an immutable TypedDict, but that's not currently a part of the type system.

We could add something like `class BaseDatum(TypedDict, immutable=True)` to disallow modifications; this would make it safe to allow covariance in child classes.
 
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: jelle.zijlstra@gmail.com