# Static types

Static types declare the shape of every value a program handles, and
the compiler enforces that declaration before the program runs.
Mainstream static typing is the type-checking layer most working
programmers encounter day-to-day — TypeScript, Python with mypy,
Kotlin, Swift, Haskell, OCaml. The technique catches a specific
class of representational, null, and shape errors at zero per-bug
cost.

## What it catches

- **Representational errors.** Treating a string as a number,
  swapping argument order, calling a method that doesn't exist.
- **Shape errors.** Field renames, missing branches in a switch
  over a sum type, undefined-when-expected-defined.
- **Null and missing-value errors** (in systems with non-null
  types). Optional vs required is checked at every call site.
- **Refactor safety.** With full type coverage, the compiler points
  at every call site a field rename breaks.
- **API drift.** A library that changed its signature fails the
  consumer's type check on the next bump.

What types do **not** catch: logic bugs that respect the declared
types, off-by-one errors at runtime, anything beyond the type
system's expressive reach. Types prove *the absence of one bug
class*, never *the presence of correctness*.

## Patterns worth knowing

The following type-system patterns recur across stacks
and repay their configuration cost.

- **Make impossible states impossible** (the Elm pattern). Encode
  domain states as a sum type — `Loading | Loaded(Data) | Failed(Error)`
  — so the compiler refuses code that tries to read `Data` from a
  `Loading` value.
- **Exhaustive pattern matching.** When the type system enforces
  every case of a sum type, the compiler catches the case you
  forgot when you added a new variant — the strongest argument for
  sum types over strings in domain code.
- **Opaque / nominal types** to prevent accidental mixing. A
  `Metres` and a `Feet` that are both `f64` underneath are still
  mutually unassignable. The Mars Climate Orbiter is the canonical
  example of what happens without this.
- **Newtype wrappers for invariants.** `EmailAddress`, `UserId`,
  `NonEmptyString` — a constructor enforces the invariant once;
  thereafter the type guarantees it.
- **IO validation at the boundary.** Static types vanish at
  serialization; boundary validators ([Zod](https://zod.dev/), io-ts,
  valibot, [Pydantic](https://docs.pydantic.dev/)) generate runtime checks from
  the same schema. See
  [schema and boundary validation](https://quality.stereobooster.com/schema-and-boundary-validation.md)
  for the runtime side.

## Tools

- **[TypeScript](https://quality.stereobooster.com/typescript.md)** with `strict: true` (especially
  `strictNullChecks`, `noUncheckedIndexedAccess`,
  `exactOptionalPropertyTypes`). The canonical gradual-typing
  case study.
- **Python** with **[mypy](https://github.com/python/mypy) --strict** or **[pyright](https://github.com/microsoft/pyright)** / **[basedpyright](https://github.com/DetachHead/basedpyright)**.
  Same trade-offs as TypeScript.
- **Kotlin** with `-Xexplicit-api=strict`; nullable types via `?`;
  sealed classes for sum types.
- **Swift** — non-null by default; optionals are explicit;
  exhaustive `switch` over enums.
- **Haskell** with strict warnings (`-Wall -Werror`); algebraic
  data types; type classes; higher-kinded types.
- **OCaml** / **F#** — Hindley-Milner inference, sum types,
  exhaustiveness checking.
- **Scala 3** — strong sum types via enums; opaque types; match
  expressions with exhaustiveness.
- **Java** with `record` (since 16) and sealed classes (since 17), null
  annotations (JSR-305 / Checker Framework / [NullAway](https://github.com/uber/NullAway)).
- **C#** with `nullable` reference types and record types.
- **Go** generics (since 1.18) — relatively limited; the
  type-system case for Go remains modest by comparison.

## When to use, when not

**Use:**

- Every new project in a typed or gradually-typable language. The
  marginal cost of turning on strict mode at project start is
  near-zero.
- Existing projects in a typed language with strictness flags off.
  A team ratchets one flag at a time and fixes the diffs it
  exposes, so each step costs no more than that flag.
- API boundaries. A type at the boundary documents the contract
  for humans *and* compilers.

**Don't:**

- Treat types as a substitute for tests. Types prove shape; tests
  prove behavior.
- Treat *unsound* types as a substitute for runtime validation
  *at* the boundary. Zod, Pydantic, Joi exist precisely because
  unsound types don't survive deserialization.
- Lean on `any` / `Object` / `dynamic`. Each use is a hole in
  the proof.

## Evidence

- **Gradual typing catches a specific bug class.** Around 15% of
  public JavaScript bug-fix commits in the studied sample would
  have been caught by gradual typing (Gao et al. 2017)[^gao2017].
- **But not the overall bug rate.** Across 604 JS/TS GitHub
  projects, code quality and complexity were significantly better
  in the TS sample, while **bug-rate reduction was not
  statistically significant** (Bogner and Merkel 2022)[^bogner2022].
- **A development-time penalty in a controlled experiment.**
  Among 49 subjects implementing a parser over 27 hours, the
  statically typed group took significantly longer to reach a
  working scanner, and the test cases the finished parsers passed
  showed no significant difference (Hanenberg 2010)[^hanenberg2010].
- **Cross-language defect study, contested and unresolved.** An
  initial mining study reported small cross-language effects
  (Ray et al. 2014)[^ray2014]; a reproduction could not confirm most of them after
  methodology corrections (Berger et al. 2019)[^berger2019]; the original authors
  rebutted the reproduction, arguing their (small) effects still
  stand (Ray et al. 2019)[^ray2019]; and an independent Bayesian reanalysis of the
  same data left the question unsettled (Furia et al. 2022)[^furia2022]. Weak,
  disputed evidence either way.
- **Industrial anecdote.** Airbnb's 2019 internal postmortem
  estimated ~38% of post-mortemed bugs could have been prevented
  by TypeScript (Bunge 2019)[^bunge2019] — a single company's classification
  rather than a controlled study, and 2.5× the effect the
  gradual-typing study measured.

No result here quantifies a caught bug class outside gradually-typed
JavaScript, so the stronger guarantee a sound type system offers
stands unmeasured at comparable scale.

## Classification

- **Quality dimensions:** Functionality, Maintainability.
- **Area:** General programming; any compiled or gradually-typed language; the everyday static-checking layer in modern stacks.
- **Guarantee:** Exhaustive within what the type system can express — **only when the system is sound**. Most mainstream type systems are deliberately unsound at one or more boundaries; see the [types overview](https://quality.stereobooster.com/types.md) for the soundness discussion.

## Referenced by

- [Effect scope](https://quality.stereobooster.com/effect.md) · The axes
- [Contracts and runtime assertions](https://quality.stereobooster.com/contracts-and-runtime-assertions.md) · Methods
- [Dead-code detection](https://quality.stereobooster.com/dead-code-detection.md) · Methods
- [Linear types](https://quality.stereobooster.com/linear-types.md) · Methods
- [Schema and boundary validation](https://quality.stereobooster.com/schema-and-boundary-validation.md) · Methods
- [Types and effects](https://quality.stereobooster.com/types.md) · Methods
- [Verifying memory safety](https://quality.stereobooster.com/memory.md) · Methods
- [Verifying time and date handling](https://quality.stereobooster.com/time-and-date.md) · Methods
- [TypeScript](https://quality.stereobooster.com/typescript.md) · Recipes
- [How AI fits into software quality](https://quality.stereobooster.com/ai.md) · AI
- [Glossary](https://quality.stereobooster.com/glossary.md) · Overview

## References

[^gao2017]: Gao, Zheng, Christian Bird, and Earl T. Barr. 2017. "[To Type or Not to Type: Quantifying Detectable Bugs in JavaScript](https://earlbarr.com/publications/typestudy.pdf)." *Proceedings of the 39th International Conference on Software Engineering (ICSE '17)*, 758–69. <https://doi.org/10.1109/ICSE.2017.75>.
[^bogner2022]: Bogner, Justus, and Manuel Merkel. 2022. "[To Type or Not to Type? A Systematic Comparison of the Software Quality of JavaScript and TypeScript Applications on GitHub](https://arxiv.org/pdf/2203.11115)." *Proceedings of the 19th International Conference on Mining Software Repositories (MSR '22)*, 658–69. <https://doi.org/10.1145/3524842.3528454>.
[^hanenberg2010]: Hanenberg, Stefan. 2010. "[An Experiment about Static and Dynamic Type Systems: Doubts about the Positive Impact of Static Type Systems on Development Time](https://static.aminer.org/pdf/20170130/pdfs/oopsla/cb1nxlpgo2mxev746jswtoifd9fkek3d.pdf)." *Proceedings of OOPSLA '10*, 22–35. <https://doi.org/10.1145/1869459.1869462>.
[^ray2014]: Ray, Baishakhi, Daryl Posnett, Vladimir Filkov, and Premkumar Devanbu. 2014. "[A Large Scale Study of Programming Languages and Code Quality in GitHub](https://web.cs.ucdavis.edu/~filkov/papers/lang_github.pdf)." *Proceedings of the 22nd ACM SIGSOFT International Symposium on Foundations of Software Engineering (FSE '14)*, 155–65. <https://doi.org/10.1145/2635868.2635922>.
[^berger2019]: Berger, Emery D., Celeste Hollenbeck, Petr Maj, Olga Vitek, and Jan Vitek. 2019. "[On the Impact of Programming Languages on Code Quality: A Reproduction Study](https://arxiv.org/pdf/1901.10220.pdf)." *ACM Transactions on Programming Languages and Systems* 41 (4): 1–24. <https://doi.org/10.1145/3340571>.
[^ray2019]: Ray, Baishakhi, Premkumar Devanbu, and Vladimir Filkov. 2019. *[Rebuttal to Berger et al., TOPLAS 2019](https://arxiv.org/pdf/1911.07393)*. arXiv:1911.07393. <https://doi.org/10.48550/arXiv.1911.07393>.
[^furia2022]: Furia, Carlo A., Richard Torkar, and Robert Feldt. 2022. "[Applying Bayesian Analysis Guidelines to Empirical Software Engineering Data: The Case of Programming Languages and Code Quality](https://arxiv.org/pdf/2101.12591)." *ACM Transactions on Software Engineering and Methodology* 31 (3): 1–38. <https://doi.org/10.1145/3490953>.
[^bunge2019]: Bunge, Brie. 2019. *[Adopting TypeScript at Scale](https://www.youtube.com/watch?v=P-J9Eg7hJwE)*. <https://www.youtube.com/watch?v=P-J9Eg7hJwE>.
