typescript-type-safety · git:20260909.ac8ab3f · 2026-09-09 · sha256 bf4bb366585fa3f7

typescript-type-safety git:20260909.ac8ab3fA

Immutable. This exact content never changes and is served at /api/v1/blob/bf4bb366585fa3f7.

---
name: typescript-type-safety
description: Represent valid state and relationships in TypeScript so invalid combinations fail at compile time. Use when designing types, parsing unknown input, or removing unsafe assertions.
metadata:
  shadowclone-category: typescript
  shadowclone-section: engineering
  shadowclone-applies-when: language=typescript and changing typed state or boundaries
---
# Represent State in TypeScript Types

## Use when

Use this skill when values change together, optional fields encode hidden states, external input enters typed code, or a type assertion is needed to make the compiler accept an operation.

## Process

1. Name the domain states and the transitions the code permits.
2. Replace groups of independent optional fields with a discriminated union when only certain combinations are valid.
3. Preserve relationships between keys and values with generics, mapped types, or a typed setter rather than erasing both to broad primitives.
4. Accept external data as `unknown` and validate it once at the boundary.
5. Narrow values through predicates, control flow, schema results, or destructuring before use.
6. Make absence explicit when it is a valid state and impossible when the caller must supply a value.
7. Return a result type that forces callers to handle meaningful failure modes.
8. Run the type checker and tests that exercise runtime validation at the boundary.

## Guardrails

- Keep one source of truth for each state discriminator.
- Prefer exhaustive switches where every union member requires behavior.
- Preserve literal relationships instead of widening values to `string` or `number` too early.
- Use runtime validation for files, network responses, environment values, and parsed JSON or YAML.
- Treat `any`, non-null assertions, and broad type assertions as evidence that a boundary or relationship is missing.
- Use a narrow assertion only when the runtime invariant is established outside TypeScript and cannot be expressed through validation or control flow.
- Avoid generic abstractions that make a local relationship harder to read than explicit types would.

When a library returns an imprecise type, contain the adaptation in one boundary function. Return a precise project type so unsafety does not spread through callers.

## Completion

The work is complete when valid states are directly constructible, invalid combinations are rejected by validation or the compiler, key-value relationships survive through the call path, the type checker passes, and no new unsafe escape is left unexplained at a boundary.