This rule raises an issue when a dataclass attribute is assigned a value without a type annotation, suggesting the developer likely intended an instance field but silently created a class variable instead.

Why is this an issue?

The @dataclass decorator only processes attributes that have type annotations. Attributes without annotations are silently excluded from dataclass processing and become regular class variables instead of instance attributes. This means:

What is the potential impact?

Unannotated attributes are silently excluded from initialization, \__repr__, and \__eq__, making them invisible to the dataclass contract. These bugs are difficult to trace because the class appears to work normally, but the affected attributes do not participate in any of the generated methods.

How to fix it

Add type annotations to all attributes that should be dataclass fields.

If you intentionally want a class variable shared across all instances, annotate it with typing.ClassVar[T]. This is the idiomatic Python way to declare class variables inside a dataclass. It makes the intent explicit and ensures the attribute is excluded from all generated dataclass methods.

Code examples

Noncompliant code example

from dataclasses import dataclass

@dataclass
class Config:
    timeout = 30  # Noncompliant: missing type annotation
    retries = 3   # Noncompliant: missing type annotation

Compliant solution

from dataclasses import dataclass

@dataclass
class Config:
    timeout: int = 30
    retries: int = 3

Noncompliant code example

from dataclasses import dataclass

@dataclass
class Registry:
    instance_count = 0  # Noncompliant: intended as a class variable, but not explicit

Compliant solution

from dataclasses import dataclass
from typing import ClassVar

@dataclass
class Registry:
    instance_count: ClassVar[int] = 0  # Explicit class variable, excluded from __init__

Resources

Documentation