Safety
Advanced

Runtime Validation and Schema Boundaries

Design safe boundaries between TypeScript and untrusted JSON, queues, webhooks, storage, and vendor SDKs.

48 min
3 sections
runtime-validation
schema
unknown
boundaries
1
2
3

01. The Compile-time vs Runtime Line

Section 1 of 3

TypeScript proves facts about code you compile. It does not prove that an API response, webhook body, localStorage value, queue message, or feature flag service returned the shape you expected. Enterprise apps need a repeatable boundary strategy: accept unknown, validate once, convert to trusted types, then keep the rest of the app strongly typed.

typescript
type ParseResult<T> =
  | { ok: true; value: T }
  | { ok: false; issues: string[] };

type VendorSubscriptionEvent = {
  id: string;
  type: "subscription.created" | "subscription.cancelled";
  customerId: string;
  occurredAt: string;
};

function parseSubscriptionEvent(input: unknown): ParseResult<VendorSubscriptionEvent> {
  if (typeof input !== "object" || input === null) {
    return { ok: false, issues: ["Expected object"] };
  }

  const record = input as Record<string, unknown>;
  const issues: string[] = [];

  if (typeof record.id !== "string") issues.push("id must be a string");
  if (record.type !== "subscription.created" && record.type !== "subscription.cancelled") {
    issues.push("type must be a known subscription event");
  }
  if (typeof record.customerId !== "string") issues.push("customerId must be a string");
  if (typeof record.occurredAt !== "string") issues.push("occurredAt must be an ISO string");

  if (issues.length > 0) return { ok: false, issues };

  return {
    ok: true,
    value: {
      id: record.id as string,
      type: record.type as VendorSubscriptionEvent["type"],
      customerId: record.customerId as string,
      occurredAt: record.occurredAt as string,
    },
  };
}

Exercise

Validate a queue message

Practice

Create a parser for a queue message that provisions a tenant. It should validate orgId, requestedBy, plan, and traceId and return structured validation issues.

Back to Course