How to Validate Dataclass Fields with Python Type Hints
A beginner-friendly helper that checks if instance attributes match their declared type hints using dataclasses and get_type_hints.
Python code
38 linesfrom typing import Any, TypeVar, get_type_hints
from dataclasses import dataclass
T = TypeVar("T")
@dataclass
class User:
name: str
age: int
email: str
def validate_fields(obj: Any) -> dict[str, bool]:
"""Check if object attributes match declared type hints."""
hints = get_type_hints(obj.__class__)
results = {}
for field, expected_type in hints.items():
value = getattr(obj, field, None)
results[field] = isinstance(value, expected_type)
return results
def print_validation_report(obj: Any) -> None:
"""Display validation results in a readable format."""
report = validate_fields(obj)
for field, is_valid in report.items():
status = "✅ valid" if is_valid else "❌ invalid"
print(f"{field}: {status}")
if __name__ == "__main__":
# Test with correct data
valid_user = User(name="Alice", age=30, email="alice@example.com")
print("Valid user validation:")
print_validation_report(valid_user)
print()
# Test with incorrect data type (age as string, should fail)
bad_user = User(name="Bob", age="thirty", email="bob@example.com")
print("Invalid user validation:")
print_validation_report(bad_user)
Output
Valid user validation:
name: ✅ valid
age: ✅ valid
email: ✅ valid
Invalid user validation:
name: ✅ valid
age: ❌ invalid
email: ✅ valid
How it works
This code uses get_type_hints to retrieve the declared type annotations for each field of a dataclass. For each field, it grabs the actual attribute value with getattr and uses isinstance to compare it against the expected type. Because Python evaluates isinstance with a class type, the helper naturally handles primitive types like str and int. This approach is a lightweight alternative to full validation libraries like Pydantic, and it works entirely with the standard library. The dataclass decorator automatically adds a __init__ that stores the given values, so attributes are always present on the instance.
Common mistakes
- Using `type(value) is expected_type` instead of `isinstance`, which fails for subclass instances.
- Forgetting that `get_type_hints` requires all annotations to be importable at runtime.
- Assuming `get_type_hints` works on non-dataclass classes; it works on any class with annotations.
- Not handling `Optional` types, where `isinstance(value, Optional[int])` would raise TypeError.
Variations
- Use a dedicated library like Pydantic for automatic validation with more advanced rules.
- Recursively validate nested dataclasses by checking if an attribute is a dataclass instance and calling `validate_fields` on it.
Real-world use cases
- A quick runtime check before saving user input to a database in a small Flask or FastAPI app.
- Validating configuration objects loaded from environment variables or config files at startup.
- A debugging aid in existing codebases to spot mismatched types without rewriting models.
Sponsored
More from Testing & modern typing
- Capture stdout and stderr with pytest capsys easy
- Characterization Test for Legacy Python Code medium
- Dataclass with Type Hints Fields in Python easy
- Dependency Injection in Python for Testability easy
- Design Data Helpers with Python TypedDict and Literal easy
- Fix and Test a Regression Bug in Python with Unit Tests easy
Keep learning
Related tutorials and quizzes for this topic.