High any density in core business logic means TypeScript's safety guarantees are opt-out rather than opt-in across the most critical code paths. ISO 25010:2011 §6.5.5 treats this as a reliability defect: when an API response shape changes, a database column is renamed, or a third-party SDK updates its return type, any-saturated code compiles without complaint and fails silently or noisily at runtime. A practical threshold is fewer than 15% of typed positions using any — above that, the type checker is too porous to catch refactoring regressions.
High because pervasive `any` usage renders TypeScript's compile-time safety effectively optional, meaning refactoring regressions and API shape changes surface only at runtime.
Replace any with unknown for values with genuinely unknown types, then narrow at the usage site. Work through the highest-traffic files first — src/lib/, src/services/, and API handlers typically have the most impact.
// Bad: loses all type information
function processResponse(data: any) {
return data.result.items;
}
// Good: preserves type safety with runtime validation
function processResponse(data: unknown): Item[] {
if (!isApiResponse(data)) throw new Error('Unexpected API response shape');
return data.result.items;
}
To measure your starting point: npx type-coverage --detail reports the percentage of fully-typed nodes across the project.
ID: code-quality-essentials.type-safety.type-coverage
Severity: high
What to look for: Estimate the prevalence of any typing across the codebase. Sample 10-20 source files from src/, app/, and lib/. In each file, count: (1) explicit any annotations on function parameters, return types, or variable declarations; (2) as any type casts; (3) untyped function parameters (which may be implicitly any if strict mode is off). Additionally, check whether @typescript-eslint/no-explicit-any is present in the ESLint config — if so, any violations are caught automatically. High any usage is a leading indicator of future runtime crashes that TypeScript would have prevented. Aim for "any" appearing in fewer than 15% of typed positions.
Pass criteria: Enumerate all relevant code locations. Sparse any usage — any appears in fewer than 15% of observable typed positions, primarily in well-justified utility code or third-party interop. ESLint no-explicit-any rule may be configured.
Fail criteria: Frequent any throughout core application logic; any used as a shortcut rather than a deliberate choice; more than 3 occurrences per sampled file on average.
Skip (N/A) when: Project has no TypeScript files.
Detail on fail: "High frequency of 'any' type usage detected in core files; estimated coverage below 85%" (add specific examples if found)
Remediation: Replace any incrementally with specific types. Use unknown for values with genuinely unknown types, then narrow at runtime:
// Bad: loses all type information
function processResponse(data: any) {
return data.result.items;
}
// Good: preserves type safety with runtime validation
function processResponse(data: unknown): Item[] {
if (!isApiResponse(data)) throw new Error('Unexpected API response shape');
return data.result.items;
}
To audit systematically: npx type-coverage --detail generates a report showing percentage of typed nodes.