Unlock the Power of Python with Typing Extensions Introduction and Dozens of Useful API Examples

Introduction to Typing Extensions

The typing-extensions module is a powerful library that provides backport compatibility for modern type hints introduced in newer versions of Python. With Python’s growing focus on static type checking, this library enables developers to use advanced typing features even in older Python versions.

Let’s dive into its dozens of useful APIs with practical examples.

1. Literal

The Literal type is useful when you want to restrict a variable to specific values.

  from typing_extensions import Literal

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

  print(get_status("success"))  # Valid
  # print(get_status("unknown"))  # Throws a type error

2. TypedDict

TypedDict allows you to create dictionary-like structures with type annotations for keys and values.

  from typing_extensions import TypedDict

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

  user: User = {"id": 1, "name": "John", "email": "john@example.com"}
  print(user)

3. Final

The Final modifier can be used to declare that a variable or method should not be overridden.

  from typing_extensions import Final

  PI: Final = 3.14159

  # PI = 3.14  # Throws a type error

4. @runtime_checkable

The @runtime_checkable decorator allows interfaces and protocols to be used for runtime type checks.

  from typing_extensions import Protocol, runtime_checkable

  @runtime_checkable
  class MyProtocol(Protocol):
      def execute(self) -> None:
          pass

  class MyClass:
      def execute(self) -> None:
          print("Executing...")

  obj = MyClass()
  print(isinstance(obj, MyProtocol))  # True

5. Annotated

The Annotated type lets you add metadata to a type for better documentation or runtime processing.

  from typing_extensions import Annotated

  def process_data(data: Annotated[int, "Positive value only"]) -> None:
      assert data > 0, "Value must be positive"
      print(f"Processing {data}")

  process_data(42)

6. Self

The Self type lets you annotate methods that return instances of their own class.

  from typing_extensions import Self

  class FluentBuilder:
      def __init__(self):
          self.value = ""

      def append(self, text: str) -> Self:
          self.value += text
          return self

      def build(self) -> str:
          return self.value

  builder = FluentBuilder()
  result = builder.append("Hello").append(", World!").build()
  print(result)

7. Example App Using Typing Extensions APIs

Let’s create a simple library catalog app using the TypedDict, Literal, and other features introduced above.

  from typing_extensions import TypedDict, Literal, Annotated


  class Book(TypedDict):
      id: int
      title: str
      author: str
      status: Literal["available", "borrowed"]


  def add_book(catalog: list[Book], book: Book) -> None:
      catalog.append(book)


  def find_books_by_author(catalog: list[Book], author: str) -> list[Book]:
      return [book for book in catalog if book["author"] == author]


  def check_book_status(book: Book) -> str:
      return f"Book '{book['title']}' is {book['status']}."


  # Create a sample catalog
  catalog: list[Book] = []
  add_book(catalog, {"id": 1, "title": "1984", "author": "George Orwell", "status": "available"})
  add_book(catalog, {"id": 2, "title": "Brave New World", "author": "Aldous Huxley", "status": "borrowed"})

  # Search for books by author
  orwell_books = find_books_by_author(catalog, "George Orwell")
  print(orwell_books)

  # Check book status
  print(check_book_status(catalog[0]))

This example demonstrates how TypedDict, Literal, and other APIs work together to provide type safety, clarity, and functionality to Python programs.

Start using typing-extensions in your projects today and experience the power of modern type annotations!

Leave a Reply

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