Expand Your Python Typing Skills with Typing Extensions

Introduction to typing-extensions

typing-extensions is a highly useful Python package that provides backports of new type system functionality from newer versions of Python’s standard library’s typing module. This allows developers to use the latest typing features even when they’re working on older versions of Python (e.g., 3.6, 3.7, or 3.8). It ensures compatibility while leveraging advanced type hints, which make your code more robust, readable, and maintainable.

In this blog post, we’ll not only cover the basics of typing-extensions, but also explore its several APIs through examples and even build a simple app that uses these features.

Key APIs in typing-extensions with Examples

1. TypedDict

Introduced in Python 3.8, TypedDict allows you to create type-annotated dictionaries. You can define a dictionary schema for better clarity in code:

  from typing_extensions import TypedDict

  class Movie(TypedDict):
      title: str
      release_year: int
      genre: str

  inception = Movie(title="Inception", release_year=2010, genre="Sci-Fi")
  print(inception)

2. Literals

The Literal type lets you restrict variable values to specific constants:

  from typing_extensions import Literal

  def get_status(status: Literal["success", "error", "loading"]) -> str:
      return f"Status is: {status}"

  print(get_status("success"))
  # print(get_status("pending"))  # This will raise a static type-checking error.

3. Protocol

Protocol is a way to define structural subtyping, where objects are considered a subtype if they implement the required methods and attributes:

  from typing_extensions import Protocol

  class Flyable(Protocol):
      def fly(self) -> None:
          ...

  class Bird:
      def fly(self) -> None:
          print("Flying high!")

  def perform_flight(subject: Flyable):
      subject.fly()

  bird = Bird()
  perform_flight(bird)

4. Annotated

Use Annotated when you want to attach metadata to a type hint:

  from typing_extensions import Annotated

  def process_data(age: Annotated[int, "Must be a positive number"]) -> None:
      print(f"Processing data: {age}")

  process_data(25)

5. Final

Final ensures that variables or methods cannot be overridden or reassigned:

  from typing_extensions import Final

  API_VERSION: Final = "1.0"
  # API_VERSION = "2.0"  # This will cause a type-checking error.

Building an Application Example: Movie Catalog

Let’s combine these APIs into a practical example. We’ll create a movie catalog app that demonstrates how typing-extensions makes type hints robust and expressive.

  from typing_extensions import TypedDict, Literal, Final, Protocol

  # Define the dictionary schema for movies
  class Movie(TypedDict):
      title: str
      release_year: int
      genre: Literal["Action", "Comedy", "Drama", "Sci-Fi"]

  # Define the Flyable protocol (for animated effects)
  class Flyable(Protocol):
      def fly(self) -> None:
          ...
  
  class AnimationEffect:
      def fly(self) -> None:
          print("Animated flying effect!")

  # Movie catalog constants
  GENRES: Final = ["Action", "Comedy", "Drama", "Sci-Fi"]

  # Function to add a movie
  def add_movie(catalog: list[Movie], title: str, release_year: int, genre: Literal["Action", "Comedy", "Drama", "Sci-Fi"]) -> None:
      movie: Movie = {"title": title, "release_year": release_year, "genre": genre}
      catalog.append(movie)

  # Function to display movies
  def display_movies(catalog: list[Movie]) -> None:
      for movie in catalog:
          print(f"{movie['title']} ({movie['release_year']}) - {movie['genre']}")

  # Main application logic
  if __name__ == "__main__":
      catalog: list[Movie] = []

      add_movie(catalog, "Inception", 2010, "Sci-Fi")
      add_movie(catalog, "The Dark Knight", 2008, "Action")
      
      print("Movie Catalog:")
      display_movies(catalog)

      # Use the Flyable protocol for a fun effect
      effect = AnimationEffect()
      effect.fly()

Why Use typing-extensions?

The typing-extensions library accelerates your Python development by allowing you to leverage new type hints even on older Python versions. This ensures your applications are future-proof and easier to work with in the long run. Whether you’re dealing with APIs or building complex programs, typing-extensions is an invaluable tool to have in your Python toolkit.

Happy Typing!

Leave a Reply

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