pythonadvanced

Python Advanced Typing Patterns

Advanced type hints with Protocol, TypeVar, Generic, overload, and TypeGuard for safer code.

python
from typing import (
    Protocol, TypeVar, Generic, overload, TypeGuard,
    Literal, runtime_checkable, Union,
)
from collections.abc import Callable, Sequence

T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)


# Protocol: structural subtyping (duck typing with types)
@runtime_checkable
class Serializable(Protocol):
    def to_dict(self) -> dict: ...


def save(obj: Serializable) -> None:
    data = obj.to_dict()
    print(f"Saving: {data}")


# Generic container
class Result(Generic[T]):
    def __init__(self, value: T | None = None, error: str | None = None):
        self._value = value
        self._error = error

    @property
    def is_ok(self) -> bool:
        return self._error is None

    def unwrap(self) -> T:
        if self._error:
            raise ValueError(self._error)
        return self._value  # type: ignore

    @classmethod
    def ok(cls, value: T) -> "Result[T]":
        return cls(value=value)

    @classmethod
    def err(cls, error: str) -> "Result[T]":
        return cls(error=error)


# Overloaded function signatures
@overload
def parse(data: str) -> dict: ...
@overload
def parse(data: bytes) -> dict: ...
@overload
def parse(data: list) -> list[dict]: ...

def parse(data: str | bytes | list) -> dict | list[dict]:
    if isinstance(data, bytes):
        data = data.decode()
    if isinstance(data, str):
        import json
        return json.loads(data)
    return [parse(item) for item in data]


# TypeGuard for type narrowing
def is_string_list(val: list[object]) -> TypeGuard[list[str]]:
    return all(isinstance(x, str) for x in val)


items: list[object] = ["a", "b", "c"]
if is_string_list(items):
    # items is now list[str]
    print(", ".join(items))


# Usage
result: Result[int] = Result.ok(42)
if result.is_ok:
    print(result.unwrap())

Use Cases

  • Building type-safe generic containers
  • Structural typing with Protocol interfaces
  • Type narrowing with custom TypeGuards

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.