TypeDrop
2026-10-19 Challenge
2026-10-19
Easy
Typed Shopping Cart Reducer
You're building the cart logic for a lightweight e-commerce checkout flow. Cart actions arrive as a discriminated union, and a pure reducer must apply each action to produce a new typed cart state — the compiler must enforce that every action variant carries exactly the right payload and that the derived totals always stay in sync.
Goals
- Define CartItem, CartState, and a four-variant CartAction discriminated union with correctly typed payloads.
- Implement cartReducer as a pure function that handles all four action types and keeps totals in sync.
- Use Omit<CartItem, 'quantity'> for the ADD_ITEM payload and Pick<CartState, ...> for the computeTotals return type.
- Add an exhaustive default branch using a never variable so the compiler catches any unhandled action variant.
challenge.ts
// Core types you must define:
export type CartItem = {
id: string;
name: string;
priceInCents: number;
quantity: number;
};
export type CartState = {
items: CartItem[];
totalItems: number;
totalPriceInCents: number;
};
// Four-variant discriminated union (yours to complete):
export type CartAction = never; // ← replace with your union
// Pure reducer — compiler must catch any unhandled action variant:
export function cartReducer(state: CartState, action: CartAction): CartState {
// switch on action.type ...
throw new Error("Not implemented");
}
Hints (click to reveal)
Hints
- A `never`-typed variable in the default branch (e.g. `const _exhaustive: never = action`) is the idiomatic way to get compile-time exhaustiveness checking in a switch.
- For ADD_ITEM, search `state.items` for an existing id first — if found, map over items to increment quantity; otherwise spread in a new item with quantity 1.
- computeTotals only needs a single Array.reduce pass to accumulate both totalItems and totalPriceInCents simultaneously.
Useful resources
Or clone locally
git clone -b challenge/2026-10-19 https://github.com/niltonheck/typedrop.git