Search code examples
pythonmypypython-typing

How to instantiate a large number of NotRequired arguments in a TypedDict?


Consider this contrived example:

from typing import Mapping, Union, MutableMapping
from typing_extensions import TypedDict, NotRequired



class Pet(TypedDict):
    softness: NotRequired[int]
    name: NotRequired[str]

# **IMPORTANT**: Assume these are only known at run time.
softness_exists = False
name_exists = True

optargs: MutableMapping[str, Union[int, str]] = dict()

if softness_exists:
    optargs['softness'] = 999999

if name_exists:
    optargs['name'] = 'David'

p = Pet(
    type='Dog',
    #Unsupported type "MutableMapping[str, Union[Food, int, str]]" for ** expansion in TypedDict
    **optargs
)
print(p)

In my real world use case, I have a relatively large number of optional arguments. Enough that conditionally populating optargs based on the run-time input is the only wieldy way to accomplish the construction of the TypedDict.

But this does not appear to be allowed. What is the recommended way to construct a TypedDict with a large number of NotRequired fields, whose applicability is decided at run time?

I am suspecting that the decision on which NotRequired fields present in an instantiation of a TypedDict cannot be decided at run time.


Solution

  • You don't need to unpack anything. Just set entries in the final dict directly:

    p: Pet = {}
    if softness_exists:
        p['softness'] = 999999
    if name_exists:
        p['name'] = 'David'
    

    (I've omitted type, since that's not actually a valid Pet key, but that doesn't have anything to do with the issue at hand.)