"If the compiler can't tell what type something is, it shouldn't default to 'anything goes.'"
What it catches
Without noImplicitAny, the compiler silently types un-annotated, non-inferable values as any. A function parameter with no annotation and no callsite to infer from? any. A variable declared without initialization or annotation? any. The 'don't check me' type spreads through your codebase without warning.
With the flag on, every such case becomes a compile error. You must either annotate or rewrite the code so inference can succeed. Explicit any (: any) is still allowed — the flag only catches the implicit case.
Why it's the most important strict flag
Of the seven strict-family flags, noImplicitAny catches the broadest category of latent unsafety. It's the foundation; the others build on it. Turn this on first when migrating an unstrict codebase to strict.
The migration playbook
On a legacy codebase, turning on noImplicitAny usually produces hundreds of errors. The migration path:
- Annotate hot-path public APIs first.
- Sweep through file-by-file from leaves inward.
- Use the IDE's quick-fix to insert
anyexplicitly for the truly-untyped cases. This makes the implicitanys visible without breaking anything. - Replace each explicit
anywith a real type over time.
noImplicitAny is the line between 'type system catches my bugs' and 'type system shrugs and lets things through.' Always on.