Skip to content
Sarj Code Standards

prefer-runtime-validation

Prefer runtime validation to TypeGuard assertions.

Why

TypeGuard tells the type checker to trust a predicate's claimed result; its annotation performs no runtime validation. Returning a validated domain value keeps the accepted schema and downstream contract together.

Fix

At data boundaries, validate into a named Pydantic model or TypeAdapter and return the validated value. For type dispatch, use actual isinstance checks or match class patterns. Do not replace TypeGuard with a cast or merely change its annotation to TypeIs. Explain indispensable low-level refinements with a local exact-code exception.

Examples

Before — flagged A claimed narrowing is not a schema validator
app/records.py
from typing import TypeGuard
def is_record(value: object) -> TypeGuard[dict[str, str]]:
return isinstance(value, dict)
After — preferred Return a validated domain value
app/records.py
from pydantic import BaseModel
class Record(BaseModel):
name: str
def parse_record(value: object) -> Record:
return Record.model_validate(value)