microsoft / pyright

Static Type Checker for Python
Other
13.13k stars 1.4k forks source link

Type of dataclass Field.type incorrectly reported as Any | str #8429

Closed adampauls closed 2 months ago

adampauls commented 2 months ago

Describe the bug Field.type on in dataclasses was recently changed to have type Type[_T] | str | Any. However, pyright seems to think the type is Any | str.

Code or Screenshots


from dataclasses import dataclass, fields

@dataclass
class Foo:
    x: int

for field in fields(Foo):
    # reveal_type(field.type)  # Type of "field.type" is "Any | str"
    print(type(field.type)) # prints "<class 'type'>"

**VS Code extension or command-line**
Command line 1.1.371. 
erictraut commented 2 months ago

Pyright is working as intended here, so I don't consider this a bug.

The fields function is defined as follows in typeshed:

def fields(class_or_instance: DataclassInstance | type[DataclassInstance]) -> tuple[Field[Any], ...]: ...

Not surprisingly, mypy's behavior is the same here.

adampauls commented 2 months ago

I'm sorry, I don't understand your response. Indeed the type of fields is a tuple of fields. My issue is that the type of field.type does not match the typeshed declaration. I suppose that now that Any is in the type, there's no point in having type[T] in the union (nor str for that matter), but it's still jarring that pyright's type does not match the typeshed declaration.

erictraut commented 2 months ago

Ah, I see what you mean now. You expected the resulting type to be type[Any] | str | Any.

Here's a code sample that demonstrates this more clearly.

from dataclasses import Field
from typing import Any

def func(x: Field[Any]):
    reveal_type(x.type) # should be type[Any] | str | Any

I agree this is a bug, and it will be fixed in the next release.

erictraut commented 2 months ago

This is addressed in pyright 1.1.372.