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!