Types as Interfaces

How programming languages model “types as interfaces” exposes deep trade-offs between expressiveness, composability and real‑world ergonomics. Commenters compare approaches ranging from object-oriented interfaces and mixins to row types, extensible records, refinement and dependent types, using languages like Haskell, TypeScript, OCaml, Idris and Rust as reference points. Many see richer type systems as a way to encode more invariants and prevent bugs, but warn that stronger or sounder types often bring complexity, rigidity and performance costs that can outweigh their benefits outside of high-assurance domains.

Scope of the Discussion

  • Centered on how to model behavior and structure: types vs interfaces, records vs maps, and how far type systems should go in expressing invariants.
  • Strong focus on practical tradeoffs between theoretical elegance and real‑world ergonomics and evolution of codebases.

Professional Practice and “Basic” Type Modelling

  • Some commenters argue this is a “first‑year” problem and most professionals just ship code without overthinking elegance.
  • Others push back, saying even experienced programmers regularly get data modelling wrong and revisiting fundamentals is valuable.
  • Consensus: there is rarely an “obviously optimal” design; tradeoffs only become clear as software evolves.

Row Typing, Extensible Records, and Map‑like Types

  • Several posts discuss “row typing” / “extensible records”: statically known maps from field names to types that can be merged and extended.
  • Languages mentioned as supporting this (with varying ergonomics) include PureScript, Elm, Haskell, OCaml, Scala 3, C++, Ceylon, TypeScript, and others.
  • Advantages: composability (e.g., mergeMaps Foo Bar), avoiding repeated field listings, and more generic code over “has field X” constraints.
  • Concerns: ceremony, performance vs nominal types, clunky syntax, and unclear real‑world payoff relative to simple structs/records.

Types vs Interfaces / Behavior vs Shape

  • One view: interfaces describe behavior (methods), types describe structure/shape; mixing them increases complexity.
  • Counter‑view: structure is part of observable behavior; you must know shapes and types of values to use APIs correctly.
  • Some note language differences: in TypeScript and C#, interfaces can be purely structural; elsewhere, they’re more behavior‑oriented.
  • Object‑oriented analogs (interfaces, traits, mixins) are compared to Haskell typeclasses and record constraints; composition without duplication remains tricky.

Soundness, Pragmatism, and TypeScript

  • TypeScript’s type system is praised as highly expressive but explicitly unsound.
  • Some argue unsoundness is a feature: it allows typing idiomatic JavaScript and keeps the language practical.
  • Others emphasize that unsoundness limits how much you can rely on types as specifications, but still greatly reduces bugs via “sanity checks.”
  • Discussion contrasts “clean” foundations (Idris, Scala 3, etc.) with messy but effective systems like TypeScript.

Dependent, Refinement, and Richer Types

  • Several participants want types to encode all known invariants (ranges, refined subsets, domain rules), citing dependent types (Idris, Coq, etc.) and refinement types (Liquid Types, Ada predicates, SPARK).
  • Benefits: stronger guarantees, constraints propagated through the system, fewer runtime checks.
  • Pushback: high cognitive and tooling cost, rigidity, difficulty composing evolving systems, and theoretical limits (halting problem).
  • Suggested compromise patterns include “parse, don’t validate” and branded/newtypes that validate once and then use stronger types.

Schemas, Maps, and Evolution

  • Debate over “just use maps” / schemaless approaches:
    • One side: schemaless systems still have implicit schemas; pushing validation to every consumer is error‑prone.
    • Other side: partial/implicit schemas ease evolution, coexistence of versions, and rapid change.
  • Examples raised: Protobuf’s move away from required, default values, and how database schemas parallel type‑system constraints.