typing.Literal in Python: Restrict Values addresses a recurring problem in Python projects: Express that an input accepts specific values rather than every string or integer. This guide explains the mechanism, provides an executable example, and identifies the boundaries that keep an implementation reliable.
Concept and use case
Literal tells a type checker that only listed values are valid. It works well for modes, states, and discriminated-union tags.
For the related fundamentals, also read the type hints guide. Integration stays simpler when functions receive dependencies and data explicitly instead of relying on global state.
Practical example
from typing import Literal
type Mode = Literal["read", "write", "append"]
def open_store(mode: Mode) -> None:
...
open_store("read")
## open_store("reed") # type checker error
Create an alias when the set repeats, and choose Enum when values carry behavior or metadata or must be enumerated at runtime.
Important decisions
The correct choice depends on the public contract, expected volume, and failure behavior.
Consider concurrency, empty inputs, and partial failures. Document every limit that affects consumers and choose names that express intent.
Common mistakes
A minimal example does not replace bounds, error handling, and observability. Literal does not validate calls at runtime. External data still needs validation. Very large sets make annotations difficult to maintain.
Avoid catching exceptions without context or returning partial output as if it were complete. An explicit failure is usually safer than silently incorrect data.
How to validate
Validate behavior, not only the happy path. Run the type checker with accepted and rejected values, and retain runtime tests at JSON and user-input boundaries.