8. Typing APIs & external data
TypeScript · 44 pages source format
API responses are unknown until validated. Type fetch JSON with interfaces. Zod or manual guards for runtime check. unknown vs any — always prefer unknown for external data. Typed environment variables and module augmentation preview.
What you'll learn
- Typing fetch responses
- unknown vs any
- Type guards
- Zod lite
- Env typing
Type API responses
Define Post interface matching JSONPlaceholder. getPost(id: number): Promise<Post>. Trust but verify at boundaries.
interface Post {
id: number
userId: number
title: string
body: string
}
async function getPost(id: number): Promise<Post> {
const res = await fetch(`${BASE}/posts/${id}`)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json() as Promise<Post> // trust + validate in prod
}Do this now
Type all fetch functions with explicit return types. No bare Promise<any>.
unknown over any
any disables checking. unknown requires narrowing before use. JSON.parse returns any by default — cast to unknown first.
Do this now
Write parseJson(raw: string): unknown. Narrow with typeof/object check before use.
Type guards
function isPost(val: unknown): val is Post { return typeof val === "object" && val !== null && "title" in val }.
Do this now
Implement isPost guard. Use in getPost before return.
Zod lite (optional)
npm install zod. PostSchema = z.object({...}). PostSchema.parse(data) throws on mismatch — runtime + static types.
import { z } from "zod"
const PostSchema = z.object({
id: z.number(),
userId: z.number(),
title: z.string(),
body: z.string(),
})
type Post = z.infer<typeof PostSchema>Do this now
Add Zod schema for Post. Parse response in getPost. Export type Post = z.infer<typeof PostSchema>.
Typed environment
declare ImportMetaEnv in vite-env.d.ts. Validate env at startup. Fail fast on missing VITE_API_BASE.
Do this now
Add vite-env.d.ts with interface ImportMetaEnv { readonly VITE_API_BASE: string }.