Skip to content

no-shallow-record-type-guard

Do not promise a local record's contract from a container-only check.

Why

An empty dict or tuple passes a container-only check while lacking a TypedDict's required key or a NamedTuple's named attributes and record API. A guard annotation makes callers trust that missing contract.

Fix

Validate the required record shape and field contracts, or keep an honest container return type. For a NamedTuple, checking its actual class can establish nominal membership; tuple membership alone cannot.

Examples

Before — flagged A dictionary check does not prove a required key
app/guards.py
from typing import TypedDict, TypeGuard
class Payload(TypedDict):
text: str
def is_payload(value: object) -> TypeGuard[Payload]:
return isinstance(value, dict)
After — preferred Unchecked contents retain a container contract
app/guards.py
from typing import TypedDict, TypeGuard
class Payload(TypedDict):
text: str
def is_payload(value: object) -> TypeGuard[dict[object, object]]:
return isinstance(value, dict)
Before — flagged Tuple membership does not establish a named record
app/guards.py
from typing import NamedTuple, TypeGuard
class Payload(NamedTuple):
text: str
def is_payload(value: object) -> TypeGuard[Payload]:
return isinstance(value, tuple)
After — preferred Check the actual named tuple class for nominal membership
app/guards.py
from typing import NamedTuple, TypeGuard
class Payload(NamedTuple):
text: str
def is_payload(value: object) -> TypeGuard[Payload]:
return isinstance(value, Payload)