5

I have an existing TypedDict containing multiple entries:

from typing import TypedDict
class Params(TypedDict):
    param1:str
    param2:str
    param3:str

I want to create the exact same TypedDict but with all the keys being optional so that the user can specify only certain parameters. I know I can do something like:

class OptionalParams(TypedDict, total=False):
    param1:str
    param2:str
    param3:str

but the problem with this method is that I have to duplicate the code. Is there a way to inherit from Params by making the keys optional ? I tried to do

class OptionalParams(Params, total=False):
    pass

but the linter does not understand that the parameters are optional

bad_coder
  • 11,289
  • 20
  • 44
  • 72
Gabriel
  • 857
  • 10
  • 14

2 Answers2

4

What you ask for is not possible - at least if you use mypy - as you can read in the comments of Why can a Final dictionary not be used as a literal in TypedDict? and on mypy's github: TypedDict keys reuse?. Pycharm seems to have the same limitation, as tested in the two other "Failed attempts" answers to your question.

When trying to run this code:

from typing import TypeDict

params = {"a": str, "b": str}
Params = TypedDict("Params", params)

mypy will give error: TypedDict() expects a dictionary literal as the second argument, thrown here in the source code.

edd313
  • 1,109
  • 7
  • 20
1

No, you cannot do this for the same set of fields. Quoting from PEP 589.

The totality flag only applies to items defined in the body of the TypedDict definition. Inherited items won’t be affected, and instead use totality of the TypedDict type where they were defined. This makes it possible to have a combination of required and non-required keys in a single TypedDict type.

It's possible to construct required and non required keys with a single TypedDict type.

>>> class Point2D(TypedDict, total=False):
...     x: int
...     y: int
...
>>> class Point3D(Point2D):
...     z: int
...
>>> Point3D.__required_keys__ == frozenset({'z'})
True
>>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
True

But you have same set of keys(param1, param2, param3) that needs to be mandatory and optional. Hence that has be inherited from TypedDict separately with total=False

class OptionalParams(TypedDict, total=False):
    param1:str
    param2:str
    param3:str
Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46