How to Type Hint a Decorator in Python
Decorators are a concept that can trip up new Python users. You may find this definition helpful: A decorator is a function that takes in another function and adds new functionality to it without modifying the original function.
Functions can be used just like any other data type in Python. A function can be passed to a function or returned from a function, just like a string or integer.
If you have jumped on the type-hinting bandwagon, you will probably want to add type hints to your decorators. That has been difficult until fairly recently.
Let’s see how to type hint a decorator!
Type Hinting a Decorator the Wrong Way
You might think that you can use a TypeVar to type hint a decorator. You will try that first.
Here’s an example:
If you run mypy —strict info_decorator.py you will get the following output:
That’s a confusing error! Feel free to search for an answer.
The answers that you find will probably vary from just ignoring the function (i.e. not type hinting it at all) to using something called a ParamSpec.
Let’s try that next!
Using a ParamSpec for Type Hinting
The ParamSpec is a class in Python’s typing module. Here’s what the docstring says about ParamSpec:
In short, you use a ParamSpec to construct a parameter specification for a generic function, class, or type alias.
To see what that means in code, you can update the previous decorator to look like this:
Here, you create a ParamSpec and a TypeVar. You tell the decorator that it takes in a Callable with a generic set of parameters (P), and you use TypeVar (R) to specify a generic return type.
If you run mypy on this updated code, it will pass! Good job!
What About PEP 695?
PEP 695 adds a new wrinkle to adding type hints to decorators by updating the parameter specification in Python in 3.12.
The main thrust of this PEP is to “simplify” the way you specify type parameters within a generic class, function, or type alias.
In a lot of ways, it does clean up the code as you no longer need to import ParamSpec of TypeVar when using this new syntax. Instead, it feels almost magical.
Here’s the updated code:
Notice that at the beginning of the function you have square brackets. That is basically declaring your ParamSpec implicitly. The “R” is again the return type. The rest of the code is the same as before.
When you run mypy against this version of the type hinted decorator, you will see that it passes happily.
Wrapping Up
Type hinting can still be a hairy subject, but the newer the Python version that you use, the better the type hinting capabilities are.
Of course, since Python itself doesn’t enforce type hinting, you can just skip all this too. But if your employer like type hinting, hopefully this article will help you out.







I agree with everyone that this is more and more Java and no longer Python, nothing about this is intuitive or easy or straightforward and the whole type hint system has no user friendly guide or documentation, it's just a bunch of long documents with endless symbols