๐—ง๐˜†๐—ฝ๐—ฒ-๐—ฆ๐—ฎ๐—ณ๐—ฒ ๐—”๐—ฃ๐—œ ๐—–๐—น๐—ถ๐—ฒ๐—ป๐˜๐˜€ ๐—ช๐—ถ๐˜๐—ต๐—ผ๐˜‚๐˜ ๐—–๐—ผ๐—ฑ๐—ฒ๐—ด๐—ฒ๐—ป

Stop using as User for API responses.

The as User cast is a lie you tell your compiler. TypeScript thinks the data is correct. At runtime, the data is often wrong. Bugs surface three functions later. The stack trace does not help.

The network is where you trust nothing. Verify data at the boundary.

Use Zod. Define a schema once. Zod gives you the type and the check. Your types will not drift.

Build a simple fetch wrapper. Pass a schema into it. Use safeParse to check the body. Data becomes a type only after the check.

Do not throw errors. Return a Result object. Use a union with ok: true or ok: false. This forces you to handle failures.

Apply the same logic to your URLs. Schema your query parameters. Prevent typos before the request leaves.

Use Zod when:

Use codegen when:

A cast is not a check. Treat as User as a code smell near fetch.

Parse at the boundary. Trust inside.

Source: https://dev.to/pavelespitia/type-safe-api-clients-in-typescript-without-a-code-generator-1k32