In python, how can I make a dict/typeddict that has a default type and type hints for known keys (additionalProperties implementation)?

Question:

In python, how can I make a dict that has type hints for know keys and a default type for unknown keys?

I have tried using a typing.TypeDict but I do not see how to set the type on the unknown key type.

import typing
class SomeDict(typing.Typeddict):
    a: str
    b: int

some_dict = SomeDict({"a": "a", "b": 0, "c": 3.14})
val_a = some_dict.get("a")
val_b = some_dict.get("b")
val_c = some_dict.get("c")

This would be especially helpful if an IDE like pycharm or vscode could correctly see the type of the value stored in the dict.

Asked By: spacether

||

Answers:

This is possible today in visual studio code (vscode).
See the below working example.

import typing

class SomeDict(dict):

    @typing.overload
    def __getitem__(self, name: typing.Literal["a"]) -> str: ...

    @typing.overload
    def __getitem__(self, name: typing.Literal["b"]) -> int: ...

    @typing.overload
    def __getitem__(self, name: str) -> float: ...

    def __getitem__(self, name):
        return super().__getitem__(name)

...

some_dict = SomeDict({"a": "a", "b": 0, "hi there": 1.234})
val_a = some_dict["a"]  # str
val_b = some_dict["b"]  # bool
another_val = some_dict["hi there"]  # float

Validating those inputs is left up to the developer
One could implement that in __new__ or __init__.
Hopefully pycharm will support this soon in https://youtrack.jetbrains.com/issue/PY-42137/PyCharm-type-hinting-doesnt-work-well-with-overload-decorator

And with the soon to be added python 3.11 PEP 675 addition of typing.LiteralString one could

  • require that only string literals are passed in, and that generic strings are not passed in (if one wanted)
  • or set the type hint on str to include all of the overloaded types because that would happen when a non-literal string is passed in

But this is only for retrieval of properties, it is not for assigning properties to the dict 🙁

Answered By: spacether