Understanding Typing Extensions for Python Enhance Your Python Codebase

Introduction to typing-extensions

As Python continues to grow as one of the most popular programming languages, maintaining type safety and making codebases more robust has become a priority. Enter the typing-extensions library—a companion to Python’s built-in typing module. typing-extensions provides backports of typing features added in newer versions of Python, enabling developers to use these features in older Python versions. Additionally, it introduces experimental features that may be included in future Python versions.

In this blog, we will take a closer look at typing-extensions by exploring dozens of its powerful APIs, complemented with practical examples and even an app showcasing how to integrate these features effectively.

Dozens of Handy APIs in typing-extensions

1. TypedDict

TypedDict allows you to define dictionaries with a fixed structure, similar to defining models in a static type system.

  from typing_extensions import TypedDict

  class Movie(TypedDict):
      title: str
      year: int
      rating: float

  # Example usage
  my_movie: Movie = {"title": "Inception", "year": 2010, "rating": 8.8}

2. Literal

Use Literal to define specific literal values that a variable can accept.

  from typing_extensions import Literal

  def set_status(status: Literal["success", "error", "pending"]) -> str:
      return f"Status set to: {status}"

  print(set_status("success"))

3. Final

Final is used to declare constants or methods that should not be overridden or reassigned.

  from typing_extensions import Final

  PI: Final = 3.14159  # Cannot be reassigned

  class Base:
      def greet(self) -> str:
          return "Hello"

  class Derived(Base):
      greet: Final = lambda: "Welcome"  # Error: Cannot override 'Final' method

4. Annotated

Annotated allows attaching metadata to types for better clarity or validation purposes.

  from typing_extensions import Annotated

  def calculate_area(radius: Annotated[float, "should be non-negative"]) -> float:
      return 3.14159 * radius ** 2

  print(calculate_area(5.0))

5. Self

The Self type allows you to annotate methods that return an instance of their class.

  from typing_extensions import Self

  class Builder:
      def set_option(self) -> Self:
          # Configure the builder
          return self

      def build(self) -> str:
          return "Object created!"

  builder = Builder().set_option().build()

6. Required and NotRequired

These two types fine-tune the requirements for keys in a TypedDict.

  from typing_extensions import TypedDict, Required, NotRequired

  class Config(TypedDict):
      host: Required[str]
      port: Required[int]
      timeout: NotRequired[int]

  server_config: Config = {"host": "localhost", "port": 8080}

Practical Example: Task Management App with typing-extensions

Let’s build a simple task management application using some of the features from typing-extensions:

  from typing_extensions import TypedDict, Literal, Final

  class Task(TypedDict):
      id: int
      title: str
      status: Literal["pending", "in-progress", "completed"]

  TASK_ID_COUNTER: Final = 1

  def create_task(title: str) -> Task:
      global TASK_ID_COUNTER
      task: Task = {"id": TASK_ID_COUNTER, "title": title, "status": "pending"}
      TASK_ID_COUNTER += 1
      return task

  def change_status(task: Task, new_status: Literal["pending", "in-progress", "completed"]) -> Task:
      task["status"] = new_status
      return task

  # Example Usage
  task1 = create_task("Write blog post about typing-extensions")
  task1 = change_status(task1, "in-progress")
  print(task1)

Conclusion

The typing-extensions library is a powerful companion for Python developers aiming to leverage type annotations effectively. Whether it’s about enforcing type safety or using forward-compatible APIs, typing-extensions is a crucial tool for any modern Python project. Start integrating it into your project today to write cleaner and more robust code!

Leave a Reply

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