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.