How do I type JSON from an external API safely

Back to list2023-09-25
You

How do I type JSON from an external API safely?

ChatGPT

Parse, do not cast. A cast is a promise you cannot keep:

const User = z.object({ id: z.number(), email: z.string().email() });
type User = z.infer<typeof User>;
const user = User.parse(await res.json());

The runtime check is the point: as User compiles happily and fails at three in the morning instead.

You

Is unknown really better than any?

ChatGPT

Yes, because it forces a check before use. any disables the checker silently and spreads through everything it touches; unknown keeps the value opaque until you narrow it, which is exactly the discipline you wanted when you reached for a type.

You

How do I model loading and error states without booleans?

ChatGPT

A discriminated union removes impossible states:

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "ok"; data: User[] }
  | { status: "error"; message: string };

With three booleans you can represent loading and error simultaneously; with this you cannot, and the compiler enforces handling each case.

You

How long does this usually take in practice?

ChatGPT

An afternoon to do it properly the first time, then minutes when it recurs. Most of the first afternoon goes into discovering which of the defaults do not match your situation.