Default value for dataclass field with bound TypeVar type
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
I have a base class `Base` and a few subclasses thereof (`A`, `B`). I also have a class `HasTp` that has an attribute `tp` of type `type[Base]` (not `Base`) with default value `A`. Now I want to make `HasTp` generic over `type[Base]`. When I use a regular class with an explicit `__init__` method, pyright is happy, but when I use a dataclass with `field(default=A)` I get an error.
That surprises me, as I had the impression that the dataclass version is basically equivalent to the regular class version with less boilerplate. Or are there differences that justify the typing error in the dataclass case?
```python
from dataclasses import dataclass, field
from typing import Generic, TypeVar, reveal_type
class Base: ...
class A(Base): ...
class B(Base): ...
BaseT = TypeVar("BaseT", bound=Base)
class HasTp(Generic[BaseT]):
tp: type[BaseT]
def __init__(self, tp: type[BaseT] = A) -> None:
self.tp = tp
@dataclass
class DHasTp(Generic[BaseT]):
tp: type[BaseT] = field(default=A) # Error: Type "type[A]" is not assignable to declared type "type[BaseT@DHasTp]"
reveal_type(HasTp()) # Type of "HasTp()" is "HasTp[A]"
reveal_type(HasTp(B)) # Type of "HasTp()" is "HasTp[B]"
reveal_type(DHasTp()) # Type of "DHasTp()" is "DHasTp[A]"
reveal_type(DHasTp(B)) # Type of "DHasTp()" is "DHasTp[B]"
```
[playground link](https://pyright-play.net/?pythonVersion=3.11&strict=true&code=GYJw9gtgBAJghgFzgYwDZwM4YKYagSwgAcwQFZEV0sAaKYfbVGAKFEigQE8j8A7AOYFipcgHFsfbCHzI6AFR7YAanBB0Q2AG7Y4qAPrci2FqbSY8AIUzYAXFAB0T0y3NYoAQQAU1nAEp7JwcXNysfGwDHZ1NfbHkoAF4oRWNVEC8AIlj5DLoAIzAAVz4YBNi-EOo8AAlMeSIvCSkZZABtbIBdAJYoXs4ieyNsdpt5DtM%2B2GxgKH19fnwEOa8cVGB8zHwMQaURnDHEzz8oAFoAPigAOTApWx7JvtXgBwQiQ7zNjBcAAXgkUNcVSgABFahh6o1JNJZHs4l07pNXjtjLCDkkGEwYF4YNM4IVUAgEh5jlAAMTJJRQDJDVoeDoZAh4PhgcgWfACPhwPKobCcMBTcyaGCcSnU3bZb6gupEekuTQ6PSGJReMEQvwk8kpXlgGYZVUNPwMrZU-W02Xy3QGIYq6U%2BdW9TWUnUm22Gxku8FEdrm7SWpXGLxSz1ee1kinGKDOjJBtVGvDR010jIsC2K60xg0a8Pa3UZkNxqkZ70ZIA)
Interestingly, despite the typing error in the dataclass field declaration, instantiated objects are still inferred correctly.
Due to internal restrictions this is on Python 3.11, but with latest pyright 1.1.408
Contributor guide
Research direction
Start with the Python 3.11 strict reproduction in the linked Pyright playground, comparing the explicit __init__ version with the dataclass field(default=A) version. Trace how the dataclass generic field declaration is checked, then verify the fix against the reported error and the reveal_type results for both default and explicitly supplied values.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100