TypeDrop
2026-05-16 Challenge
2026-05-16
Easy
Typed User Session Aggregator
You're building the analytics layer for a SaaS dashboard. Raw session events arrive as `unknown` from a browser telemetry API; your engine must validate them, group them by user, and return a strongly-typed per-user session summary report — with zero `any`.
Goals
- Declare the `UserId` branded type and a `Result<T, E>` discriminated union from the provided stubs.
- Implement `validateSessionEvent` to safely narrow `unknown` → `SessionEvent`, returning typed success or failure.
- Define `EventCounts` as a mapped type over `EventCategory` (no hand-written properties).
- Implement `aggregateSessions` to group valid events by user and produce a fully-typed `AggregationReport` with correct totals, revenue, unique paths, and sorted summaries.
challenge.ts
// Key types you'll work with:
export type EventCategory = "pageview" | "click" | "error" | "purchase";
export type UserId = string & { readonly _brand: "UserId" };
export type Result<T, E> =
| { ok: true; value: T }
| { ok: false; error: E };
export type EventCounts = { [K in EventCategory]: number }; // mapped type
export interface UserSessionSummary {
readonly userId: UserId;
readonly totalEvents: number;
readonly eventCounts: EventCounts;
readonly firstSeen: number;
readonly lastSeen: number;
readonly totalRevenueCents: number;
readonly uniquePaths: ReadonlyArray<string>;
}
// Functions you must implement:
export function validateSessionEvent(raw: unknown): Result<SessionEvent, string> { ... }
export function aggregateSessions(rawEvents: unknown[]): AggregationReport { ... }
Hints (click to reveal)
Hints
- For `EventCounts`, think `{ [K in EventCategory]: number }` — a single mapped type expression covers all four categories at once.
- To validate the `category` field at runtime without `any`, define a `const CATEGORIES: ReadonlyArray<EventCategory>` tuple and use `.includes()` after narrowing to `string`.
- A `Map<UserId, UserSessionSummary>` (or a mutable intermediate type) is a clean way to accumulate per-user data; convert it to a sorted array at the end.
Useful resources
Or clone locally
git clone -b challenge/2026-05-16 https://github.com/niltonheck/typedrop.git