Generating types from OpenAPI, and trusting them too far

Generated types describe what the specification says, and the specification is a document rather than a runtime guarantee.

import type { paths } from './api-types'

type Order = paths['/orders/{id}']['get']['responses'][200]
  ['content']['application/json']

const order: Order = await res.json()   // an assertion, not a check

// what actually happened: the API returned null for a field
// typed as string, because a nullable column had never had
// a null in it until that week.

res.json() returns any and assigning it to a generated type is a claim, not a validation — the compiler is satisfied and the runtime is not. Parsing the response through a schema validator at the boundary is the fix and it costs a few kilobytes; doing it only on the three responses that come from outside our control was the compromise that stuck.