Homework

Homework — a trusted boundary

Homework — a trusted boundary.

  1. Type guard. In src/lib/api.ts write isApod(value: unknown): value is Apod and request(): Promise<unknown>. Have fetchPictures return data.filter(isApod).
  2. Prove the hole. Temporarily change request's return to Promise<any> and assign directly const pics: Apod[] = data. The compiler is silent. Restore unknown — now it demands the guard. That's the difference between "I expect" and "I checked".
  3. Break the API. Simulate a changed response (e.g. an object with no url). With the guard it's simply filtered out; without it, the gallery would try to render undefined and crash.
  4. Readonly. In state.ts, have getState() return Readonly<AppState>. Try getState().pictures = [] — error. Change it through an action — works.
  5. catch unknown. In errors.ts, toMessage(error: unknown). Try error.message without instanceof — error ('error' is of type 'unknown'). Add instanceof — ok.

Required tests:

  • Boundary test: without the guard, unknown won't compile as Apod[]; with it, it's trusted.
  • Readonly test: assigning to a getState() field doesn't compile.

To submit: screenshots: (1) the any vs unknown difference (the hole), (2) the Readonly assignment error, (3) catch unknown requiring instanceof.

Next. We have solid boundaries and typed state. But so far we've turned on only basic strictness. In lesson 18 we'll see what the strict flags buy: noUncheckedIndexedAccess (an array index can be undefined), exactOptionalPropertyTypes, and assertNever — an exhaustiveness guarantee that forces you to handle every union variant.