Map

Type System Axes

Wiki conceptprogramming-languagestype-systems โ†ณ show in map Markdown
title
Type System Axes
type
concept
summary
Static/dynamic (when types are checked) and strong/weak (how much implicit coercion) are independent dimensions
tags
programming-languages, type-systems
created
2026-04-25
updated
2026-04-25

Type systems vary along two independent dimensions. Conflating them โ€” or substituting vague replacements like "strict" โ€” produces conversations where two people disagree about something neither of them has named.

Static vs dynamic โ€” when types are checked

Static typing checks types from the source code without running it. The compiler or analyzer rejects programs that fail the check; the program never executes in a state where a type error could occur at the checked sites.

Dynamic typing checks types at run time. Each value carries a type tag that the runtime inspects on demand โ€” when an operation is attempted, when a method is dispatched, when a value is unpacked.

This is distinct from untyped, which means no type checking happens at any point โ€” neither statically nor dynamically. Assembly is untyped. A dynamically-typed language is very much typed; the checks just happen later.

Strong vs weak โ€” how much implicit coercion

Strong typing means the language refuses to silently convert between types. Operations that mix types either error out or require an explicit conversion.

Weak typing means the language will quietly coerce values across type boundaries to make an operation succeed โ€” pointer arithmetic on raw bytes, numeric promotion across signedness, string-to-number coercion in comparison operators.

This dimension is about implicitness, not about whether types exist.

The two axes are orthogonal

Common confusion is to assume static implies strong and dynamic implies weak. The four-corner matrix has populated examples in every quadrant:

  • Static + weak: C. The compiler checks types statically but lets you reinterpret a char* as an int* and do arithmetic on it.
  • Static + strong: Haskell, Rust. Compile-time checking with no implicit conversions.
  • Dynamic + strong: Python. Types are checked at runtime, but "3" + 4 is an error rather than "34" or 7.
  • Dynamic + weak: JavaScript, PHP. Runtime checks, but "3" + 4 === "34" and "3" * 4 === 12.

Why "strict" and "loose" obscure things

Online discussion often substitutes "strict typing" or "loose typing" for one of the four standard terms. The substitution is unrecoverable: a reader can't tell whether "strict" means static, strong, or both. Lewis Campbell argues these terms are produced by people who haven't internalized the two-axis model and want a single slider โ€” which doesn't exist.

See type-systems-vocabulary for the source post. sqlite-strict-tables is a database instance of the weak/strong (coercion) axis: SQLite's default flexible typing coerces values to a column's affinity, and STRICT tables turn that off โ€” "strict" here names the coercion axis, not the static/dynamic one.

Sub-pages