Avoiding any and Unsafe Casts
On this page
Why any Is a Production Problem
- any disables safety and allows invalid states to flow through the system.
- Most runtime crashes in typed apps are caused by boundary casts and unchecked external data.
- Production rule: no any at boundaries and no unknown as T without validation.
Common Sources of any
- JSON parsing and API responses.
- Third party libraries without types.
- Loose event handler signatures.
- Incremental migrations that never removed temporary casts.
Replace Casts with Narrowing
function isRecord(x: unknown): x is Record<string, unknown> {
return typeof x === "object" && x !== null;
}
function getString(x: Record<string, unknown>, k: string): string {
const v = x[k];
if (typeof v !== "string") throw new Error("invalid");
return v;
}
Example: Safe Parsing Pattern
type UserVM = { id: string; name: string };
function parseUserVM(x: unknown): UserVM {
if (!isRecord(x)) throw new Error("invalid");
return { id: getString(x, "id"), name: getString(x, "name") };
}
Operational Controls
- Enable strict TypeScript settings.
- Use lint rules to ban explicit any.
- Centralize parsing and mapping at API boundaries.
- Fail fast on invalid data with explicit error state.
Failure Modes
- unknown as T used as a shortcut and invalid data enters UI state.
- Any spreads through props and reduces type signal across the tree.
- Runtime crashes occur far from the source, making incidents hard to debug.
Incident Triage Checklist
- Search for any, unknown as, and large type assertions.
- Inspect API boundary mapping functions.
- Add runtime guards where data enters the system.
- Convert boolean soup to unions to restore invariants.