microsoft / microsoft/pyright

Default value for dataclass field with bound TypeVar type

Open
#11,226 1 comment 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.