Comment by Syntaf

1 year ago

For what it's worth, TypedDict was a bit ahead of it's own time. Python 3.12 is really the turning point for being able to leverage them effectively for stuff like **kwargs[1][2]

    from typing import TypedDict, Unpack, NotRequired

    class Movie(TypedDict):
        name: str
        year: NotRequired[int]

    def foo(**kwargs: Unpack[Movie]) -> None: ...

[1] https://typing.readthedocs.io/en/latest/spec/callables.html#... [2] https://peps.python.org/pep-0692/

How does that work for partial forwarding? Back when I last checked there was no imagining a DRY solution for that even for linear cases, let alone diamond inheritance.

  # Simple case, any halfway-decent type system should be able to handle this.
  def inner(*, i): pass
  def middle(*, m, **kwargs): inner(**kwargs)
  def outer(*, o, **kwargs): middle(**kwargs)
  kwargs = ...; outer(**kwargs)

  # More complicated case, but fairly common in Python code.
  class A:
    def __init__(self, *, a):
      pass
  class B(A):
    def __init__(self, *, b, **kwargs):
      super().__init__(**kwargs)
  class C(A):
    def __init__(self, *, c, **kwargs):
      super().__init__(**kwargs)
  class D(B, C):
    def __init__(self, *, d, **kwargs):
      super().__init__(**kwargs)
  kwargs = ...; D(**kwargs)

  # An even more complicated case involves `kwargs.pop()`, forwarding without `**`.

Can the above be typechecked yet?