Glossary / Runtime validation

Runtime validation

Runtime validation checks actual values against expected rules while a program is running. It complements static TypeScript types because network responses, files, environment variables, browser storage, messages, and JavaScript consumers can supply values that do not match compile-time declarations.

From untrusted data to trusted domain values

Treat external input as unknown, validate its shape and constraints, then convert it into a domain type. Validation may check primitive types, required and optional fields, literal discriminants, array contents, numeric ranges, formats, and cross-field invariants. A schema library can centralize parsing and produce typed results; handwritten guards can be adequate for small contracts if they thoroughly check nested values.

const raw: unknown = await response.json();
if (!isUser(raw)) throw new Error('Invalid response');
useUser(raw); // narrowed after a correct runtime guard

as User, generic type parameters, interfaces, and declarations do not validate input. Validation should define whether unknown extra fields are rejected, stripped, or retained. Coercion should be intentional: turning "42" into 42 may be useful for forms but surprising for signed API payloads.

Security, compatibility, and operations

Validate authorization-sensitive fields on the server; client-side checks are not an access-control boundary. Bound input size and nesting to limit resource exhaustion. Produce useful errors without echoing secrets or untrusted markup. Version schemas deliberately and distinguish missing, null, and invalid values.

Engineering guidance

Validate once at system boundaries and pass trusted domain values inward. Keep schemas close to their API contracts, test malformed and adversarial cases, and monitor validation failure rates. Avoid redundant deep validation at every internal function unless invariants can be invalidated through mutation. Prefer immutable normalized outputs where isolation matters.

Interview questions

  1. Why validate if TypeScript compiles? Types are erased and external values can violate declarations.
  2. What type should raw JSON have? unknown until successfully checked.
  3. What does a type assertion do? Changes compiler assumptions without inspecting the value.
  4. Where should authorization validation happen? At the trusted server boundary, regardless of client checks.
  5. Reject or strip extra fields? Choose based on schema/version/security contract and make behavior explicit.

References