Exploring Typing Extensions Enhancing Python Type Hints with Powerful APIs

Unlocking the Power of typing-extensions: Advanced Type Hints in Python

The typing-extensions library is a must-have tool for developers looking to enhance their Python codebase with robust type annotations. With the advent of type hints in Python, this library provides access to cutting-edge typing features that are not yet available in the standard library. In this blog post, we’ll take a closer look at typing-extensions, explore dozens of its useful APIs, and demonstrate how they empower your development workflow. We’ll even build a small app using these types!

Why Use typing-extensions?

As Python continues to evolve, many new typing features are introduced in recent versions. The typing-extensions library brings these features to older Python versions, ensuring backward compatibility. It is widely adopted in projects requiring advanced typing capabilities and better code maintainability.

Popular APIs in typing-extensions

1. TypedDict

TypedDict lets you define dictionary types with a fixed set of keys and associated value types.

  from typing_extensions import TypedDict

  class User(TypedDict):
      name: str
      age: int
      email: str

  def greet_user(user: User) -> str:
      return f"Hello, {user['name']}!"
  
  user = {"name": "Alice", "age": 30, "email": "alice@example.com"}
  print(greet_user(user))

2. Literal

Use Literal to specify precise values that a variable can take.

  from typing_extensions import Literal

  def get_status_message(status: Literal["ok", "error", "pending"]) -> str:
      if status == "ok":
          return "All systems are operational."
      elif status == "error":
          return "There is an issue."
      else:
          return "The process is pending."

  print(get_status_message("ok"))

3. Final

A Final declares a variable as immutable or a method as non-overridable.

  from typing_extensions import Final

  API_VERSION: Final = "v1.0"

  print(API_VERSION)

4. Protocol

Protocol is used for structural subtyping or “duck typing.”

  from typing_extensions import Protocol

  class SupportsSpeak(Protocol):
      def speak(self) -> str:
          ...

  class Dog:
      def speak(self) -> str:
          return "Woof!"

  class Cat:
      def speak(self) -> str:
          return "Meow!"

  def animal_sound(animal: SupportsSpeak) -> str:
      return animal.speak()

  print(animal_sound(Dog()))
  print(animal_sound(Cat()))

5. Concatenate

Use Concatenate for defining function signatures with additional arguments.

  from typing_extensions import Concatenate, Callable, TypeVar

  T = TypeVar("T")

  def bind_user(func: Callable[Concatenate[str, T], None]) -> Callable[[T], None]:
      def wrapper(arg: T) -> None:
          username = "Alice"
          func(username, arg)
      return wrapper

  @bind_user
  def say_hello(user: str, message: str) -> None:
      print(f"{user} says: {message}")

  say_hello("Welcome to typing-extensions!")

Building a Simple App with typing-extensions

Let’s create a minimal task management app using TypedDict, Literal, and Protocol.

  from typing_extensions import TypedDict, Literal, Protocol
  from typing import List

  class Task(TypedDict, total=False):
      id: int
      title: str
      status: Literal["pending", "completed"]

  class TaskService(Protocol):
      def add_task(self, task: Task) -> None:
          ...
      def list_tasks(self) -> List[Task]:
          ...

  class SimpleTaskService:
      def __init__(self) -> None:
          self.tasks: List[Task] = []

      def add_task(self, task: Task) -> None:
          self.tasks.append(task)

      def list_tasks(self) -> List[Task]:
          return self.tasks

  task_service: TaskService = SimpleTaskService()

  task_service.add_task({"id": 1, "title": "Write Blog", "status": "pending"})
  task_service.add_task({"id": 2, "title": "Publish Blog", "status": "completed"})

  for task in task_service.list_tasks():
      print(f"Task {task['id']}: {task['title']} - {task['status']}")

Conclusion

The typing-extensions library serves as a bridge to access advanced typing features in Python. With utilities like TypedDict, Literal, Final, Protocol, and Concatenate, it empowers developers to write maintainable, type-safe code. Incorporate this into your workflows to elevate your Python projects starting today!

Leave a Reply

Your email address will not be published. Required fields are marked *