Generate TypeScript types from a REST API response
Every API you integrate means TypeScript interfaces to write and maintain. snaptype generates them automatically — from a live URL or a saved JSON file — in one command.
The problem
When you integrate a new REST API, you have two common options: cast the response to any and lose type safety entirely, or spend 20 minutes writing interfaces by hand — guessing which fields are optional, which strings are actually dates, and which values form an enum.
// Option A: give up on types
const data = await fetch("/api/users").then((r) => r.json()) as any;
// Option B: write by hand and hope you got it right
interface User {
id: number;
email: string; // is this always a valid email?
role: string; // "admin" | "user"? who knows
createdAt: string; // a date? which format?
deletedAt?: string; // nullable? optional? both?
}Neither option scales. The manual interface drifts from the real API within a sprint, and any is a silent bug factory.
The solution
snaptype inspects the actual values in a JSON response — not just the structure — and infers the most precise types it can. Email strings become z.email(), ISO dates become z.iso.datetime(), and repeated string values with a small set of variants become union literals automatically.
How it works
Point snaptype directly at a live API endpoint:
npx snaptype from-url https://api.example.com/users -o src/types/user.tsOr pass a saved JSON response file:
npx snaptype from-json api-response.json -o src/types/user.tsGiven a typical API response:
[
{
"id": 1,
"email": "alice@example.com",
"role": "admin",
"createdAt": "2024-01-15T10:30:00.000Z"
},
{
"id": 2,
"email": "bob@example.com",
"role": "user",
"createdAt": "2024-03-22T08:00:00.000Z"
},
{
"id": 3,
"email": "carol@example.com",
"role": "user",
"createdAt": "2024-04-10T14:15:00.000Z"
}
]snaptype generates a TypeScript interface:
export interface User {
readonly id: number;
email: string; // email
role: "admin" | "user";
createdAt: string; // ISO 8601
}Add --zod for a runtime-validated schema alongside your interface:
import { z } from "zod";
export const UserSchema = z.object({
id: z.number(),
email: z.email(),
role: z.enum(["admin", "user"]),
createdAt: z.iso.datetime(),
}).readonly();
export type User = z.infer<typeof UserSchema>;What you get
- Accurate types from real API data — not guesswork or copy-paste from documentation
- Semantic inference: emails → z.email(), ISO dates → z.iso.datetime(), low-cardinality strings → enums
- Zod schemas for runtime validation alongside TypeScript interfaces, in one command
- Reproducible: re-run after an API update to keep types in sync with the real shape
- Works with from-url (live endpoint) or from-json (saved response file)
Related resources
Try snaptype in 30 seconds
No account needed. Works with any JSON file or API endpoint.
npm install -D snaptype
npx snaptype from-url https://api.example.com/users -o src/types/user.ts