JSON to TypeScript

Turn any JSON payload into clean TypeScript interfaces.

JSON input
TypeScript output
export interface Location {
  city: string
  country: string
}

export interface Profile {
  title: string
  location: Location
}

export interface Project {
  name: string
  stars: number
  archived?: boolean
}

export interface Root {
  id: number
  name: string
  isActive: boolean
  roles: string[]
  profile: Profile
  projects: Project[]
}

Why convert JSON to TypeScript?

Almost every app talks to an API that returns JSON, and every one of those responses has a shape you probably want to describe with a TypeScript interface. Writing those interfaces by hand is tedious and error-prone — miss one optional field and you get runtime surprises that types were supposed to prevent.

This converter takes a real JSON payload and generates accurate, ready-to-paste interfaces in seconds. You get compile-time safety, better editor autocompletion, and a single source of truth for the data your code depends on.

There is a second, quieter benefit. Generating types from a real response tells you what the API actually returns, which is not always what its documentation claims. Fields that arrive as strings rather than numbers, timestamps in an unexpected format, and objects that are sometimes null all become visible the moment you look at the generated interface.

How to use it

Paste a JSON object or API response into the input on the left, optionally rename the root interface, and the TypeScript appears instantly on the right. Use Format JSON to tidy messy input, then Copy the generated types straight into your project. Everything runs in your browser, so it is safe to paste private payloads.

Input
{ "id": 7, "name": "Ada", "tags": ["admin"], "profile": { "city": "Jaipur" } }
Output
interface Profile {
  city: string
}

interface Root {
  id: number
  name: string
  tags: string[]
  profile: Profile
}

How types are inferred

JSON valueTypeScript type
"hello"string
42 / 3.14number
true / falseboolean
nullnull
{ … }A named, nested interface
[ { … } ]A merged interface, as Item[]
[1, "x"](number | string)[]
[]unknown[] — an empty array carries no information
missing in some rowsfield?: — marked optional

The rule underneath all of this is simple: the tool describes the sample you gave it, as precisely as that sample allows. It cannot know about a field that never appeared, and it cannot know that a number field is really an enum of three values. That is a limitation of inference, not a bug — and it is why the sample you choose matters.

Tips for the cleanest output

Give it a representative sample

A single record produces a single record’s worth of truth. If a field is sometimes absent or sometimes null, paste an array containing both cases — the tool merges the objects and marks the field optional or nullable accordingly. A three-element array showing the variation you actually expect is worth far more than one perfect example.

Name the root interface

Rename the root to something meaningful, such as User or ApiResponse, before copying. Nested interfaces are named from their keys, so a good root name makes the whole generated block read naturally in your codebase.

Strip the envelope if you only want the payload

Many APIs wrap results in { data, meta, errors }. If you only care about the item type, paste just the inner object — you will get a tighter interface without having to delete the wrapper afterwards.

Watch out for empty arrays and all-null fields

An empty array cannot tell the tool what it will eventually contain, and a field that is null in every sample will be typed as null alone. Both are places where you should edit the generated type by hand — usually to Something[] or string | null.

What generated types cannot tell you

Generated interfaces are a large head start, not a finished contract. A few things are worth adjusting by hand afterwards:

  • Dates are strings. JSON has no date type, so "2026-08-18T09:00:00Z" infers as string. Narrow it to a branded type or convert at the boundary if precision matters.
  • Enums look like plain strings. A status field that can only be "active" or "archived" infers as string. Tightening it to a union of literals is usually the single most valuable manual edit you can make.
  • Integers and floats are both numbers. TypeScript has one numeric type, so any distinction has to live in a comment or a runtime check.
  • Large integers lose precision. IDs beyond the safe integer range are typically sent as strings by well-designed APIs; if yours sends them as numbers, treat that as a bug to raise rather than a type to model.
  • Types are not validation. An interface disappears at compile time and guarantees nothing about the bytes that arrive at runtime. If the source is untrusted or unstable, parse with a runtime validator and derive the type from that schema instead.

Where this fits in a real workflow

If your API publishes an OpenAPI or GraphQL schema, generating types from that schema in your build is strictly better — it stays in sync automatically and covers every endpoint, not just the one you sampled. This tool is for everything else: a third-party API with no published schema, a webhook payload you received once, a legacy endpoint nobody documented, or a quick sanity check on what an API returns before you commit to an integration. Those cases are common enough that a fast manual converter earns its place alongside a generated client.

Verify before you depend on it

Generated interfaces describe the sample you provided, not every response the API can return. Review them against the API’s documentation, and add runtime validation for any data you do not control. Your JSON is processed entirely in your browser and is never uploaded — see the privacy policy and disclaimer.

Frequently asked questions

How does JSON to TypeScript conversion work?+
The tool parses your JSON, walks every value, and infers a TypeScript type for it — string, number, boolean, arrays, and nested objects. Nested objects become their own named interfaces, and the result is a set of clean, reusable interface definitions.
How are optional and nullable fields handled?+
When you paste an array of objects, any key that is missing from some elements is marked optional with a question mark. Values that are null are typed as null (or unioned with their other types), so your interfaces reflect the real shape of the data.
What happens with arrays of mixed types?+
Arrays are inspected element by element. Arrays of objects are merged into a single interface, while arrays holding mixed primitives become a union type — for example a mix of numbers and strings becomes (number | string)[].
Is my JSON uploaded to a server?+
No. The entire conversion runs locally in your browser. Your JSON never leaves your device, which makes the tool safe to use with private API responses and sample payloads.
Why generate TypeScript interfaces from JSON?+
Hand-writing interfaces for large API responses is slow and error-prone. Generating them from a real payload gives you accurate types in seconds, catches shape mismatches at compile time, and improves editor autocompletion across your codebase.