Search code examples
pythonmypy

Typing hinting nested dictionary with varying value types


My dictionary looks as follows:

spreadsheet_list: dict[str, dict[str, Union[str, list[str]]]] = {
    'final_kpis': {
        'gsheet_key': '1np6fM9d_BrBuDbBKWkWwUjhNypoCtto_84bLcx-HBdk', 
        'primary_key': ['KPI_Reference']
    },
    'maplecroft_risk_drivers': {
        'gsheet_key': '1rV2oXbvvXcq6glLpHu1X4e_huR4mkZ4bbcZ2cQPv_A0', 
        'primary_key': ['Commodity_type', 'Commodity', 'Country']
    }
}

I am looping over the dict with:

for name, info in spreadsheet_list.items():
    do_stuff(name, info['gsheet_key'], info['primary_key'])

Where the expected types are specified in the function args:

def do_stuff(name: str, gsheet_key: str, primary_key: list[str]):

Error returned is:

error: Argument 2 to "do_stuff" has incompatible type "str | list[str]"; expected "str"  [arg-type]
error: Argument 3 to "do_stuff" has incompatible type "str | list[str]"; expected "list[str]"  [arg-type]

I have seen this solution using TypedDict, but not for a nested dictionary.


Solution

  • What's the problem with using a TypedDict instead of a dict[str, Union[str, list[str]]]?

    import typing
    
    def do_stuff(name: str, gsheet_key: str, primary_key: list[str]):
        pass
    
    class InnerDict(typing.TypedDict):
        gsheet_key: str
        primary_key: list[str]
    
    spreadsheet_list: dict[str, InnerDict] = {
        'final_kpis': {
            'gsheet_key': '1np6fM9d_BrBuDbBKWkWwUjhNypoCtto_84bLcx-HBdk', 
            'primary_key': ['KPI_Reference']
        },
        'maplecroft_risk_drivers': {
            'gsheet_key': '1rV2oXbvvXcq6glLpHu1X4e_huR4mkZ4bbcZ2cQPv_A0', 
            'primary_key': ['Commodity_type', 'Commodity', 'Country']
        }
    }
    
    for name, info in spreadsheet_list.items():
        do_stuff(name, info['gsheet_key'], info['primary_key'])