Johnny Metz
Johnny Metz

Reputation: 6045

mypy: define types for specific keys in dynamic dictionary

I have the following dictionary representing a person that could be one of many variations. Here are just a few:

person = {"name": "Johnny"}
person = {"name": "Johnny", "age": 25}
person = {"name": "Johnny", "age": 25, "active": True}

I'm extracting certain keys and using them to print a statement. The problem arises in the type hints, where I'm getting an error saying Incompatible types in assignment (expression has type "object", variable has type "Optional[str]") when I run mypy on the script:

name: Optional[str] = person.get("name")  # mypy error here
age: Optional[int] = person.get("age")    # mypy error here
if name and age:
    print(f"In 5 years, {name} will be {age + 5} years old")

To solve this the mypy_extensions.TypedDict type seemed promising, but it appears I can't have missing or extra keys:

from mypy_extensions import TypedDict
PersonDict = TypedDict("PersonDict", {"name": str, "age": int})

# ERROR: Key 'age' missing for TypedDict "PersonDict"
person: PersonDict = {"name": "Johnny"}

# ERROR: Extra key 'active' for TypedDict "PersonDict"
person: PersonDict = {"name": "Johnny", "age": 25, "active": True}

Is there anyway to define types for specific keys in a dictionary, even if the keys in that dictionary are dynamic?

Upvotes: 4

Views: 3480

Answers (1)

Markus Unterwaditzer
Markus Unterwaditzer

Reputation: 8244

Adding total=False to your TypedDict will allow missing keys:

PersonDict = TypedDict("PersonDict", {"name": str, "age": int}, total=False)

https://mypy.readthedocs.io/en/latest/more_types.html#totality

Allowing additional keys not in the schema does not seem possible.

Upvotes: 6

Related Questions