Static and Dynamic Type Systems

Static systems check type consistency before execution, while dynamic systems attach types to values and check them as the program runs.

The question is not whether types exist. It is when the language enforces them.

Sebesta treats type systems as a design choice about when errors surface and how much flexibility a language keeps during execution. Static typing pushes more checking into the compiler. Dynamic typing delays more checking until runtime values appear.

When to reach for this

Reach for this concept whenever you are comparing languages, reading a compiler diagnostic, or deciding whether a bug should be prevented before execution or caught at runtime.

Why this matters

The timing of type enforcement changes tooling, reliability, refactoring, and debugging. It affects whether a mistake is rejected before shipping or only after a path executes in production.

The mental model

Static typing front-loads certainty

The compiler reasons about declarations and operations before the program runs. That enables earlier feedback and stronger editor tooling.

Dynamic typing front-loads flexibility

Values carry runtime tags, so the program can evolve shape as it executes. That flexibility is useful, but incompatible values can travel farther before failing.

Step through the concept

How to use this page

Follow the animation one state at a time and connect the code to the runtime behavior.

  • Step through the same idea under compile-time checking and runtime checking.
  • Watch when the error appears: before execution starts versus when the bad line actually runs.
  • Notice that the code is similar, but the language decides when to say no.
Checks before runErrors surface earlier
Compiler type-checks before executionError timing: before run
Program
1let price: string = "12";
2let tax: number = 3;
3let total: number = price + tax;
Type checker
Collect declarations
Compile-time checks

Compiler is building the symbol table.

Current output
price: string, tax: number
price
"12"
string
tax
3
number
total
pending
number
Step 1 of 3
What
The compiler records the declared types for price and tax.
Why
Static type systems reason about a program before it runs. That gives the compiler enough information to reject incompatible operations early.
Code for this pattern
let price: string = "12";
let tax: number = 3;
let total: number = price + tax;

The difference is when the language commits to the types

AspectStatic typingDynamic typing
Error timingBefore executionDuring execution
Types belong toVariables and declarationsRuntime values
Big strengthEarlier guaranteesMore flexibility while prototyping
Typical costMore up-front constraintsMore runtime uncertainty

The short version

  • Every language has to manage types somehow. The key design question is when those checks happen.
  • Static typing rejects incompatible operations before execution starts.
  • Dynamic typing lets more programs begin execution, then checks compatibility when values are used.
  • Earlier feedback improves reliability; later feedback improves flexibility.