Agent Wranglers

Data shapes Required

Never type anything as mixed or any

No mixed, any or untyped value in signatures, properties or docblocks. Each one turns off the type checker for everything it touches.

How to do it

Replace it with the type, a union of the types, or unknown that must be narrowed before use. When data comes from outside, parse it into a type first.

Example

// Bad: any spreads, and nothing is checked
function total(order: any): any { return order.lines.reduce((sum: any, l: any) => sum + l.price, 0); }

// Good: named types end to end
type OrderLine = { readonly price: number; readonly quantity: number };
function total(lines: readonly OrderLine[]): number { return lines.reduce((sum, line) => sum + line.price * line.quantity, 0); }
# Bad
def total(order: Any) -> Any: ...

# Good
@dataclass(frozen=True)
class OrderLine:
    price: int
    quantity: int

def total(lines: list[OrderLine]) -> int:
    return sum(line.price * line.quantity for line in lines)
// Bad: mixed turns off the checks
function total(mixed $order): mixed { /* ... */ }

// Good: a list of typed lines
/** @param list<OrderLine> $lines */
function total(array $lines): int { return array_sum(array_map(fn (OrderLine $line) => $line->price * $line->quantity, $lines)); }

How to check

The build fails on it. Examples are TypeScript noImplicitAny with @typescript-eslint/no-explicit-any, PHPStan level 10, which checks explicit and implicit mixed, and mypy --disallow-any-explicit.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/data-shapes/no-mixed-or-any.