Theory

Extend Cosmos — challenges

The capstone — extend Cosmos on your own, in the TypeScript build, with the same patterns. Pick at least one challenge. Each builds on what you already know — and before writing code you must answer: which types change?

Challenge A — a new sort column (easy). Add sorting the collection by the saved date (savedAt).

  • You change: the SortKey union ('title' | 'date' | 'rating' | 'savedAt'), the getFilteredSaved switch.
  • Type payoff: the moment you add 'savedAt' to SortKey, assertNever points at every switch you need to update. The compiler is your to-do list.

Challenge B — swap in a different API (medium). Replace NASA APOD with another public API (e.g. the Art Institute of Chicago's artworks).

  • You change: the Apod type (a new source — a new shape), the isApod type guard, the api.ts URL.
  • Type payoff: the compiler shows every place the old shape no longer fits. "Change the type, follow the errors" — the whole migration via the error list.

Challenge C — a new typed feature (hard). Add a "tag filter": click a tag in the collection, show only pictures with it.

  • You change: AppState (a new activeTag: string | null), a new action (setActiveTag), the getFilteredSaved logic, new UI.
  • Type payoff: Readonly<AppState> won't let a view change activeTag directly — it's forced through an action.

For each challenge, before code, answer four questions: (1) which types change? (2) where do you need a type guard? (3) which switches/assertNever will break (and that's good)? (4) do you change state only through an action? If you can answer, you understood the architecture and the types.

Tip. Use the compiler as a guide: change the type first, run npm run typecheck, and fix errors one by one until it's clean. That's "type-driven" extension: the compiler shows you what's left to do. In the vanilla build you'd have to hunt by hand.