TypeDrop

2026-02-22 Challenge

2026-02-22 Easy

Typed Event Log Parser

You're building a monitoring dashboard for a cloud platform. Raw event logs arrive as untyped JSON blobs — your job is to safely parse them into a discriminated union of strongly-typed events, then aggregate counts and extract the latest timestamp per event kind.

Goals

  • Implement `parseEvent` to safely narrow `unknown` input into a typed `AppEvent` discriminated union — no `any`, no type assertions.
  • Implement `parseEventLog` to filter an unknown array, silently dropping entries that fail validation.
  • Define `EventSummary` as a mapped type over `EventKind` so the shape automatically extends when a new kind is added.
  • Implement `summariseEvents` to aggregate event counts and track the latest timestamp per kind, seeding all keys up front for compile-time exhaustiveness.
challenge.ts
/** All supported event kinds */
type EventKind = "deploy" | "error" | "scale" | "alert";

interface AlertEvent {
  kind: "alert";
  timestamp: number;
  alertName: string;
  severity: "low" | "medium" | "high" | "critical";
}

type AppEvent = DeployEvent | ErrorEvent | ScaleEvent | AlertEvent;

/** Mapped over EventKind — adding a new kind extends this automatically */
type EventSummary = {
  [K in EventKind]: {
    count: number;
    latestTimestamp: number | null;
  };
};

/** Parse one unknown blob → typed AppEvent or null if invalid */
function parseEvent(raw: unknown): AppEvent | null { ... }

/** Parse an array of unknown blobs, silently dropping invalid entries */
function parseEventLog(raw: unknown): AppEvent[] { ... }

/** Aggregate parsed events into per-kind counts + latest timestamps */
function summariseEvents(events: AppEvent[]): EventSummary { ... }
Hints (click to reveal)

Hints

  • Use `typeof raw === 'object' && raw !== null && 'kind' in raw` to safely access fields on an `unknown` value — no casting needed.
  • A `switch` on `event.kind` after you've confirmed it's a valid `EventKind` lets TypeScript narrow each branch to the correct interface.
  • Initialise the `EventSummary` accumulator by listing every `EventKind` literal explicitly — TypeScript will flag a missing key as a compile error.

Or clone locally

git clone -b challenge/2026-02-22 https://github.com/niltonheck/typedrop.git