Static vs Dynamic Typing
That static typing prevents runtime errors. A static type system proves the properties it models and says nothing about the rest: null dereferences, index-out-of-range, division by zero, protocol violations and wrong answers all survive a clean type check unless the type system was designed to model them.
Static typing
When the codebase is large or long-lived, when refactoring must be mechanical, and when the properties you care about are ones a type system can model.
Dynamic typing
When shapes are genuinely heterogeneous or not known until run time, and when the cost of describing them exceeds the cost of testing them.
| Aspect | Static typing | Dynamic typing |
|---|---|---|
| When the check happens | Before running, on all paths, including ones no test exercises. | At the operation, on the path actually taken. |
| What it proves | Exactly the properties encoded in the types — no more. | Nothing in advance; every guarantee is a test or a run-time check. |
| Effect on the compiler | Types drive layout, dispatch and specialization. | Operations dispatch on the values, which is what costs at run time. |
| Refactoring | The checker enumerates the call sites you broke. | You find them by running the code or by grep. |
| Cost of expressiveness | Programs the type system cannot express are rejected even when correct. | Programs the reader cannot understand are accepted until they run. |
| Middle ground | Local inference reduces annotation cost without weakening the proof. | Gradual typing adds annotations incrementally, with run-time checks at the boundary. |