I think that something in the proposal I sent was missed. The key of the proposal wasn't as much of "add a special value" (which it does), but mostly "use a Union[]" (I wrote it with the new | syntax, but I think this should be the same with explicit Union[Foo, Missing]. 

I stated this because the behaviour of "holes" in dictionaries already has Union semantics. Not just in the abstract sense of "there is more than one possible behaviour when evaluating mydict['mykey'] ", but in the general properties of Unions. For example consider this TypeDict declarations:

class A(TypedDict):
    x: int
    y: int|str
    z: int|Missing

class B(TypedDict):
    x: str
    z: int

 value: A|B

Currently the type of value["x"] is int|str (the union of the types for x in both types). What happens for "holes" then?

value["z"] has type int|Missing. That is the Union[int|Missing, int] which again are the types on both sides (note that we use here that Unions can be flattened and int|int == int). value["y"] is a bit more trickier, but we can consider that there's an implicit "y: Missing" in B (for every name except "x" and "z" ) so the type of value["y"] is int|str|Missing. value["doesnotexist"] has type Missing|Missing, which due to union rules, is equivalent to Missing.

Adding some special form like "Required[int|str]" will need to define what does it mean to have Union[Required[T1], T2] and similar interactions, and in the end you will end up recreating the definition and algebraic rules for a Union, because what we have conceptually here is a Union. I know some people have expressed their concern that these standalone values are unusual (but not unheard of, we already have NoReturn), but for me this emerges from the type system.

In fact, I think we might get away defining Missing as an alias for NoReturn, because right now I see no much of a semantic difference . For example, any code after value["foo"] should be ignored in the same way as code after sys.exit() (a function with result type NoReturn). Anyway, this is an extra idea and if I am wrong this paragraph can be ignored without affecting the previous argument

Hope the example drives the idea more clearly

Best,
D.



On Mon, 25 Jan 2021 at 08:10, Tuukka Mustonen <tuukka.mustonen@gmail.com> wrote:
Just want to note that while this would be a good addition:

    class MyTypedDict(TypedDict, total=False):
        foo: Required[str]
        bar: Required[int|None]
        baz: float|None
        qed: bool

...it's still "the wrong way around". This is what people usually want:

    class MyTypedDict(TypedDict):
        foo: str
        bar: int|None
        baz: float|None|Missing
        qed: bool|Missing

Were there actually any comments on Daniel Moisset's suggestion of `| Missing`? Guido replied but maybe I don't understand the difference - if `Required[str]`, which defines the existence of the field (left side) attached to the type (right side), is considered acceptable approach, what's bad with `x|Missing`, which simply does the same?
_______________________________________________
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: dfmoisset@gmail.com