1. Home
  2. Developer tools
  3. JSON to TypeScript & Zod

JSON to TypeScript & Zod

Turn an API response or config file into TypeScript types in one paste, instead of writing interfaces by hand and getting optional fields wrong.

Free, no sign-up. Runs in your browser: nothing is uploaded.

How to use JSON to TypeScript & Zod

  1. Paste JSON, or several JSON lines from the same API.
  2. Choose TypeScript or Zod and name the root type.
  3. Copy the code or download a .ts file.

Features

  • Merges every array item and document, so keys missing anywhere become optional
  • null values become “| null”
  • interface or type alias, optional readonly
  • Zod schemas in dependency order with z.infer types
  • Recognises ISO dates and UUIDs for Zod string checks

Supported formats

You can open

  • JSON
  • JSON Lines
  • Typed or pasted text

You get

  • TS
  • Copied text

Private by design

Your files are opened and processed by your browser on this device. They are never uploaded to openWorkstand or anyone else, so the JSON to TypeScript & Zod is safe for contracts, IDs, photos and work documents. After you have used it once while online, it also works without an internet connection. How local processing works

Good to know

  • Types are inferred from the samples given; values that never appear (an enum’s other options, a field that is always null) cannot be known.

Guide

From a JSON response to TypeScript types and Zod schemas

Typing API data by hand is slow and error-prone: a field that is sometimes missing gets declared as required, a field that is sometimes null gets declared as a string, and the compiler happily trusts both. This generator reads real JSON, works out the shape of every object in it, and writes TypeScript interfaces or Zod schemas that match what the data actually contains.

How the types are inferred

Each value is classified as a string, number, boolean, null, array or object. Objects become named types: the root gets the name you choose, and nested objects are named after their key, singular for arrays, so orders holds Order items and items holds Item. When two nested objects have exactly the same keys and types, they share one type rather than producing duplicates.

Why more samples give better types

The important part is merging. Every item of every array, and every JSON document you paste as a separate line, is compared. A key that is missing from any of them becomes optional (coupon?: string). A value that is null in any of them gains | null. An integer in one place and a decimal in another become number. With a single sample, every key looks required, so paste a few real responses, ideally including edge cases such as an empty cart or a deleted account.

Optional is not nullable

TypeScript distinguishes a property that may be absent (?) from one that is present but null (| null). APIs use both, and code must handle them differently: optional chaining copes with either, but a JSON serialiser omits undefined and keeps null. The generator keeps the distinction exactly as the samples show it.

interface or type, and readonly

Choose interface for classic declarations, or type aliases if your codebase prefers them; for object shapes they behave the same for almost every purpose. Switch on readonly to mark every property readonly, which suits data you only read from an API and stops accidental mutation.

Adding runtime checks with Zod

Types disappear at runtime, so a changed API can still break your app silently. The Zod output gives you a schema for every object, declared in dependency order, plus export type User = z.infer<typeof UserSchema>, so the schema and the type never drift apart. Whole numbers are checked with .int(), ISO 8601 timestamps with .datetime({ offset: true }) and UUIDs with .uuid(). Call UserSchema.parse(data) at the edge of your app and errors show exactly which field is wrong.

A worked example

The sample user record contains an address with a null unit, two orders and a nested items list. It produces four interfaces — Address, Item, Order and User. Because only the second order has a coupon, Order reads order_id: number; total: number; items: Item[]; coupon?: string;.

What inference cannot know

Samples show what happened, not what is allowed. A status field that only ever said “active” is typed as string, not as a union of all statuses; IDs that look numeric may really be strings elsewhere. Treat the output as a strong first draft and refine it with what the API documentation promises.

Tidy the input first with the JSON Formatter, convert existing interfaces with TypeScript to Zod, or generate the same models for a Go backend with JSON to Go and a Python service with JSON to Pydantic.

Checked against the current version of the JSON to TypeScript & Zod on .

Troubleshooting

The file does not open

Check that it is one of the supported formats above and opens in another app. Damaged files and password-protected PDFs cannot be read until they are repaired or unlocked.

It is slow or stops on a very large file

Everything runs on your device, so speed depends on its memory. Close other tabs, use a computer rather than a phone, or split the file into smaller parts first.

The download did not start

Look for your browser’s download bar or icon. Some browsers ask once before a site may download files; allow it and click the button again.

Frequently asked questions

Why is a property typed unknown | null?

Because it was null in every sample, so there was nothing to infer its real type from. Find a response where the field has a value and add it as another JSON line, or edit the type by hand.

Can I paste several API responses at once?

Yes. Put each JSON document on its own line (JSON Lines). All of them are merged into one set of types, which is the best way to discover which fields are optional.

Does the Zod schema check number ranges or string lengths?

No. Sample data cannot tell you limits, so the schema checks types, presence and formats only. Add .min(), .max(), .email() or .regex() where your API documents them.

Should I use interface or type?

For object shapes both work. Interfaces can be extended and merged and give clearer error messages; type aliases are needed for unions and mapped types. Many teams use interface for objects and type for everything else.

How do I get accurate optional fields?

Paste several real responses, or an array with varied items. A key is optional only if it is missing from at least one sample, so a single sample makes every key required.

Keep working with the result

openWorkstand also includes a free workspace with documents, spreadsheets, tasks, projects and a calendar that save to a folder on your computer.