Python TypedDict

Introduced in Python 3.8, TypedDict allows you to specify the types of the keys and values in a dictionary. This is particularly useful for creating dictionaries that have a fixed structure, providing better type checking and code clarity. It is part of the `typing` module.

Features of TypedDict

Key-Value Types: Each key in a TypedDict is associated with a specific type, helping to catch type-related errors during development.

Optional Keys: You can define keys as optional by using the NotRequired type from typing_extensions (or Required for required keys).

Inheritance: TypedDict can inherit from other TypedDict classes, allowing for more complex data structures.

1. Basic Usage of TypedDict

A simple example of `TypedDict` allows you to define a dictionary with specified types for its keys and values.

Example: Defining a basic `TypedDict`.
from typing import TypedDict

class Person(TypedDict):
    name: str
    age: int

# Creating an instance of Person
person: Person = {
    "name": "Alice",
    "age": 30
}

print(person)  # Output: {'name': 'Alice', 'age': 30}

Output:
{'name': 'Alice', 'age': 30}

Explanation:
In this example, we define a `TypedDict` called `Person` that specifies two keys: `name` of type `str` and `age` of type `int`. We create an instance of `Person` with valid types and print it. The output confirms that the dictionary is correctly structured.

2. Optional Keys in TypedDict

You can define optional keys in a `TypedDict` by using the `Required` and `NotRequired` types.

Example: Defining optional keys.
from typing import TypedDict, NotRequired

class Product(TypedDict):
    name: str
    price: float
    description: NotRequired[str]  # Optional key

# Creating instances of Product
product1: Product = {
    "name": "Laptop",
    "price": 999.99
}

product2: Product = {
    "name": "Smartphone",
    "price": 499.99,
    "description": "Latest model"
}

print(product1)  # Output: {'name': 'Laptop', 'price': 999.99}
print(product2)  # Output: {'name': 'Smartphone', 'price': 499.99, 'description': 'Latest model'}

Output:
{'name': 'Laptop', 'price': 999.99}
{'name': 'Smartphone', 'price': 499.99, 'description': 'Latest model'}

Explanation:
Here, the `Product` `TypedDict` has an optional key `description`. When creating `product1`, we omit the `description`, which is acceptable. The output shows both dictionaries conforming to the defined structure, demonstrating the flexibility of optional keys.

3. Inheritance with TypedDict

You can create a new `TypedDict` that inherits from another `TypedDict`.

Example: Inheriting from a `TypedDict`.
class Electronics(Product):
    warranty: int  # Warranty period in months

# Creating an instance of Electronics
laptop: Electronics = {
    "name": "Laptop",
    "price": 999.99,
    "warranty": 24  # 2 years
}

print(laptop)  # Output: {'name': 'Laptop', 'price': 999.99, 'warranty': 24}

Output:
{'name': 'Laptop', 'price': 999.99, 'warranty': 24}

Explanation: In this case, we define `Electronics`, which inherits from `Product` and adds an additional key, `warranty`. The `laptop` dictionary includes all keys from both `Product` and `Electronics`. The output shows the complete dictionary, confirming the inheritance works correctly.

4. Using TypedDict with Functions

You can pass `TypedDict` instances to functions for better type checking.

Example: Function that takes a `TypedDict`.
def print_person(person: Person) -> None:
    print(f"Name: {person['name']}, Age: {person['age']}")

# Testing the function
print_person(person)  # Output: Name: Alice, Age: 30

Output:
Name: Alice, Age: 30

Explanation: The function `print_person` takes a `TypedDict` of type `Person` as an argument. When we pass the `person` instance to the function, it correctly accesses the keys and prints the values. The output confirms the function processes the `TypedDict` as expected.

5. Combining TypedDict with Other Types

You can combine `TypedDict` with other types like lists or tuples.

Example: Using a `TypedDict` with a list.
class Team(TypedDict):
    name: str
    members: list[Person]

# Creating a Team instance
team: Team = {
    "name": "Developers",
    "members": [
        {"name": "Alice", "age": 30},
        {"name": "Bob", "age": 25}
    ]
}

print(team)  # Output: {'name': 'Developers', 'members': [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]}

Output:
{'name': 'Developers', 'members': [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]}

Explanation:
In this example, the `Team` `TypedDict` includes a list of `Person` dictionaries as its `members`. The output shows that we can nest `TypedDict` within other data structures, preserving type safety throughout.

6. Conclusion

TypedDict in Python provides a powerful way to define dictionaries with specific key-value types, enhancing type safety and code readability. Through examples of basic usage, optional keys, inheritance, function interactions, and combinations with other types, we see how `TypedDict` can be applied in various scenarios. This feature is particularly useful in larger codebases where structured data is prevalent, making it easier to catch type-related errors during development.

Previous: Structural Pattern Matching | Next: Assignment Expressions

<
>