type-safety

Installation
SKILL.md

Type Safety

Concept of the skill

Two-layer model: a compile-time layer where the type checker verifies internal consistency (claims about values are coherent across the codebase) and a runtime layer where values from outside the program (HTTP responses, environment variables, parsed JSON, untrusted user input) have NO type until parsed, regardless of what type annotation sits next to them. The discipline is the boundary contract between these two layers: validate at I/O boundaries (parse, never assert), then trust the type inside. Layered on top: soundness (does the system rule out ALL type errors of the kinds it tracks, or only some via escape hatches?), structural vs nominal typing (do shapes match by structure or by name?), narrowing (refine a broad type by control-flow evidence), and exhaustiveness checking (force the compiler to flag uncovered cases in a discriminated union).

Distinguishes a syntactic claim from a semantic guarantee. Without type-safety as a discipline (not just a compiler flag), JSON.parse(x) as User looks identical to a validated parse — the cast is decoration, not verification. The alternative — "the compiler said it was fine, so it's fine" — fails because gradual systems like TypeScript are unsound by design (escape hatches: any, as, function bivariance, ambient declarations) and untrusted input arrives un-typed regardless of what annotation sits next to it. Type-safety replaces the "compiler-blessed" mental model with "compile-time guarantees stop at the I/O boundary, runtime validation takes over there."

Distinct from api-design, which owns the external request/response surface shape — type-safety owns the discipline of expressing internal program correctness as types, and where the type system stops at the boundary api-design defines. Distinct from testing-strategy, which owns runtime verification of behavior — type-safety owns compile-time verification of structure, and the two cover different failure modes (a function can be type-safe and behaviorally wrong, or behaviorally correct and type-unsafe). Distinct from entity-relationship-modeling, which owns persistence and entity shape — type-safety owns the in-memory type contracts that consume that shape. Distinct from input validation libraries (Zod, Yup, io-ts), which provide the runtime parsing mechanism — type-safety is the discipline that decides where parsing must happen because the type system cannot. Type safety is to programs what a passport check is to international travel — the document (type annotation) certifies identity within the issuing country's records, but on the way through customs (the I/O boundary), the document is re-verified against the actual traveler, and any mismatch is rejected before they enter the trusted zone. The wrong mental model is that a TypeScript as cast is a form of validation. It is not. The cast is a programmer-asserted claim that compiles unchecked at runtime, and JSON.parse(x) as User produces a value typed as User with zero verification that it actually has the fields a User must have. The misconception conflates two layers — the compile-time claim (which the compiler accepts) and the runtime guarantee (which the cast does nothing to establish). The discipline is to use runtime validators (Zod, io-ts, manual parse functions) at every I/O boundary and treat as as an explicit, justified, rare escape hatch — not as the default way to silence a type error.

Coverage

The discipline of using a type system to rule out classes of runtime errors before they occur. Covers what soundness means and where TypeScript (and other gradual systems) is unsound, structural vs nominal typing, type narrowing and exhaustiveness checking, the runtime boundary problem, the difference between any and unknown, when to use type assertions (rarely) and when to validate (always at I/O boundaries), and the connection to runtime validation libraries.

Philosophy of the skill

Types are claims about values; type-checking is proof-checking. A program that compiles is a program whose claims have been internally consistent — but a program is more than its compiler. Values that arrive from outside the program (HTTP responses, environment variables, parsed JSON, untrusted user input) have no type until you parse them, no matter what type annotation sits next to them.

The discipline of type-safety is to take the compile-time guarantees seriously and to know exactly where they stop. A codebase that pretends JSON.parse(x) as User is safe has confused a syntactic claim with a semantic guarantee. A codebase that validates at the boundary and trusts the type inside has correctly aligned the two layers.

In gradual systems like TypeScript, the discipline includes treating escape hatches (any, as, // @ts-ignore) as exceptional, justified, and rare — not as the default response to a type error.

Installs
2
First Seen
May 18, 2026
type-safety — jacob-balslev/skills