Incorrect overload parameter mismatch when typing decorator
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Describe the bug**
Trying to type a decorator, and I'm running into some seemingly spurious errors. I've tried to figure out what exactly causes this, to no avail.
The goal is to have the an optional `cls` parameter, and to have the return type vary based on whether it is present or absent. Mypy accepts the following code, but Pyright does not.
Apologies if this has already been reported, but I couldn't find any existing issue.
**Code **
[Pyright playground](https://pyright-play.net/?strict=true&code=GYJw9gtgBALgngBwJYDsDmUkQWEMpgBuApiADZgCGAJgDRQDClZZlARmcQFBcACRpCjS7ViwKKIDGuSjFwBtACoBdABSSyAZwBcsRMSXL6AenoAqesQAeMEJV2p8AXigAGAJRQAtAD49CAxVtLihQqAA6SJ5%2BEnIqahExCWJpOzkQQ3UtXQA5MBRiKBc8gpNzSxs7BxRnN09fRmZWDgN5eADDI39A5WVgsIioxPEpGXTMjR1uwygAHygSwuL84jKoCyhrW3tMGqK6-rCkcUnMTQWVw4HQ0XEAdzsEAJAsqfae%2Br93wyvrgZBiDAAK4gFDJVKyXCvCrbJxbOzuEJ-KAA4GgqAPShPUhI0K4qCaQGyWzQqAAIgA%2BhT4ZQqWSYQj8aiQWDJlwgA)
[Mypy playground](https://mypy-play.net/?mypy=latest&python=3.14&gist=41df62496abcd51282d3f8d5097ba4b1)
```py
from typing import overload, Callable
@overload
def decorator[T](cls: type[T], /, *, extra: int = 0) -> type[T]:
...
@overload
def decorator[T](cls: None = None, /, *, extra: int = 0) -> Callable[[type[T]], type[T]]:
...
def decorator[T](cls: type[T] | None = None, /, *, extra: int = 0):
if cls is None:
def wrapper(cls: type[T]) -> type[T]:
return decorator(cls, extra=extra)
return wrapper
setattr(cls, "__extra__", extra)
return cls
```
Pyright error message:
```py
Overloaded implementation is not consistent with signature of overload 2
Function return type "(type[T@decorator]) -> type[T@decorator]" is incompatible with type "((cls: type[T@decorator]) -> type[T@decorator]) | type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "((cls: type[T@decorator]) -> type[T@decorator]) | type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "type[T@decorator]"
Type "(type[T@decorator]) -> type[T@decorator]" is not assignable to type "(cls: type[T@decorator]) -> type[T@decorator]"
Missing keyword parameter "cls"
Position-only parameter mismatch; parameter "cls" is not position-only
Position-only parameter mismatch; expected 1 but received 0 (reportInconsistentOverload)
```
Contributor guide
Research direction
Start with the linked Pyright playground and the reduced decorator example, then trace the overload-consistency diagnostic that reports the mismatch. Reproduce the error in strict mode and verify that the valid overload set no longer produces a spurious implementation error while inconsistent overloads remain diagnosed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100