Code

src/lib/utils.ts — assertNever and indexes

In the code column — src/lib/utils.ts with assertNever, toDateParam and a generic debounce.

noUncheckedIndexedAccess in practicetoDateParam:

const iso = date.toISOString().split('T')[0];   // string | undefined
if (iso === undefined) throw new Error('Could not format date');
return iso;                                       // now just string

split('T')[0] almost always exists — but the type doesn't guarantee it, so the compiler forces you to handle undefined. One line more, but instead of expecting, you now know.

assertNever — exhaustiveness. Picture a switch over LoadStatus:

function label(status: LoadStatus): string {
  switch (status.state) {
    case 'idle':    return '';
    case 'loading': return 'Loading…';
    case 'loaded':  return 'Done';
    case 'error':   return status.message;
    default:        return assertNever(status);   // ← all variants handled
  }
}

As long as all four variants are handled, in the default branch status is never, and assertNever(status) compiles. Add a fifth variant (say { state: 'stale' }) — status in the default branch is no longer never, and assertNever stops compiling, pointing at exactly this switch.

Verify.

1. Add a 'refreshing' variant to LoadStatus. `npm run typecheck` immediately
   points at EVERY switch that doesn't handle it.
2. arr[0] without a check — error "possibly undefined".

That's strictness's gift to a growing app: change a type, and the compiler becomes your "to-do list" — it shows every place that needs updating. Otherwise you'd hunt by hand and hope you missed nothing.

Tip (generics). debounce<Args extends unknown[]> preserves the argument types of the function you pass it. A non-generic (fn: Function) would "drop" them, and you'd lose checking at the call site. Generics let you write reusable code without losing types — what lesson 7's vanilla debounce did with no guarantees at all.