Introduction to Typing-Extensions
The typing-extensions
module is an essential package for Python developers who want to leverage advanced type-hinting capabilities. It complements the built-in typing
module by providing features that have been proposed or introduced in more recent versions of Python, ensuring backward compatibility.
Key Features of Typing-Extensions
Below, we introduce a variety of APIs offered by the typing-extensions
module. Each API supports developers in writing more robust, maintainable, and type-safe code.
1. Literal
The Literal
type hint allows specifying specific values a variable can take, instead of just its type.
from typing_extensions import Literal def process_color(color: Literal['red', 'green', 'blue']) -> str: return f"Selected color: {color}" print(process_color('red')) # Valid # print(process_color('yellow')) # Type checker error
2. TypedDict
TypedDict
enables defining dictionaries with a specific structure.
from typing_extensions import TypedDict class User(TypedDict): name: str age: int user: User = {"name": "Alice", "age": 30} # Missing or extra keys will raise type checker errors
3. Protocol
The Protocol
feature allows structural subtyping, enabling you to define base classes with specific method and attribute contracts.
from typing_extensions import Protocol class Greeter(Protocol): def greet(self) -> str: ... class Person: def greet(self) -> str: return "Hello!" class Robot: def perform_task(self): return "Task done!" def say_hello(entity: Greeter) -> str: return entity.greet() print(say_hello(Person())) # Valid # print(say_hello(Robot())) # Type checker error
4. Final
The Final
type indicates that a variable or method should not be overridden or reassigned.
from typing_extensions import Final MAX_USERS: Final = 100 # MAX_USERS = 200 # Type checker error
5. @runtime_checkable
Annotations with @runtime_checkable
allow runtime verification for type compatibility.
from typing_extensions import Protocol, runtime_checkable @runtime_checkable class Runner(Protocol): def run(self) -> None: ... class Athlete: def run(self) -> None: print("Running fast!") print(isinstance(Athlete(), Runner)) # True
6. Self
Self
is useful when defining methods that return the instance of their class.
from typing_extensions import Self class FluentInterface: def set_name(self, name: str) -> Self: self.name = name return self def set_age(self, age: int) -> Self: self.age = age return self fi = FluentInterface().set_name("Alice").set_age(30)
Use Case Example
Here’s a complete example demonstrating the use of multiple typing-extensions
APIs in a single application.
from typing_extensions import Literal, TypedDict, Final, Protocol, runtime_checkable class User(TypedDict): name: str age: int MAX_AGE: Final = 100 @runtime_checkable class Validator(Protocol): def validate(self, user: User) -> bool: ... class AgeValidator: def validate(self, user: User) -> bool: return user["age"] < MAX_AGE def process_user(user: User, validator: Validator) -> Literal["valid", "invalid"]: return "valid" if validator.validate(user) else "invalid" user_data: User = {"name": "Alice", "age": 25} validator = AgeValidator() print(process_user(user_data, validator)) # Output: valid
Conclusion
The typing-extensions
module is a powerful tool to extend typing capabilities in Python, ensuring better type safety and clean, maintainable code. With its array of features like Literal
, TypedDict
, Protocol
, Final
, and more, developers can unlock the potential of strict typing in their applications.