Python typing Module

The typing module provides support for type hints in Python. Type hints are optional annotations that specify the expected types of variables, function parameters, and return values. They enable static analysis tools like mypy to catch type errors before runtime.

Use Cases:
- Annotating function signatures for documentation and IDE support
- Defining complex types like Optional, Union, and generic containers
- Creating type aliases for readability
- Using Protocol for structural subtyping (duck typing with type safety)
- Enabling runtime type checking with third-party libraries

Example 1: Function type annotations
    from typing import Optional

    def find_user(user_id: int, active_only: bool = True) -> Optional[dict]:
        """Look up a user by ID. Returns None if not found."""
        users = {1: {"name": "Alice", "active": True},
                 2: {"name": "Bob", "active": False}}
        user = users.get(user_id)
        if user and (not active_only or user["active"]):
            return user
        return None

    result: Optional[dict] = find_user(1)

Example 2: Generic types and TypeVar
    from typing import TypeVar, Sequence

    T = TypeVar("T")

    def first_or_default(items: Sequence[T], default: T) -> T:
        """Return the first item, or default if empty."""
        return items[0] if items else default

    print(first_or_default([1, 2, 3], 0))       # 1
    print(first_or_default([], "fallback"))       # fallback

Python 3.10+ allows using built-in types directly as generics (list[int] instead of List[int]), and 3.12 introduced the type statement for cleaner type alias definitions. The typing module remains essential for advanced patterns like Protocol, TypeVar, ParamSpec, and Concatenate.
