EngineeringUpdated July 22, 2026

TypeScript Practices That Keep Boundaries Honest

Strict types, validated inputs, and small domain models that make invalid states harder to represent.

TypeScriptJavaScriptBest Practices

Treat external data as untrusted

TypeScript checks code during development; it does not validate JSON returned by an API or values read from storage. Keep the boundary explicit: receive external values as unknown, validate their shape, then pass a trusted domain type into the application.

interface User {
  id: number;
  name: string;
  role: 'admin' | 'member';
}

function isUser(value: unknown): value is User {
  if (typeof value !== 'object' || value === null) return false;
  const candidate = value as Record<string, unknown>;
  return typeof candidate.id === 'number'
    && typeof candidate.name === 'string'
    && (candidate.role === 'admin' || candidate.role === 'member');
}

The cast is contained inside the validator. Code after that boundary can use User without spreading assertions across the codebase.

Model states instead of combining booleans

Several independent flags can describe impossible combinations such as loading and success at the same time. A discriminated union makes the valid states visible:

type RequestState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; message: string };

Rendering code can now switch on one property, and exhaustive checks reveal missing cases when the model changes.

Keep inference, preserve constraints

Use inference for local implementation details and explicit types at public boundaries. The satisfies operator is useful for configuration because it checks the contract without widening every literal value.

Strict TypeScript is most valuable when it clarifies ownership: validate at system edges, model the domain directly, and avoid assertions that merely silence uncertainty.

Further reading: TypeScript narrowing and satisfies.