JSON to TypeScript
100% LocalConvert JSON objects into TypeScript interfaces instantly.
Paste JSON to generate TypeScript interfaces or type aliases with inferred types.
Learn More
What is JSON to TypeScript?
Frequently Asked Questions
Technical Deep Dive
JSON to TypeScript
Paste any JSON and get clean TypeScript interfaces with proper typing. Handles nested objects, arrays, nullable values, and optional properties. Supports export keywords and readonly modifiers.
quicktype and transform.tools send samples off-box. This generator infers interfaces in the tab so staging payloads stay local.
Paste a user object with user_id and created_at. You should get userId?: or an explicit mapped field plus a nested type for objects.
One sample cannot prove optionality. Generate, then tighten with Zod or a schema if the API omits fields.
01 Type Transformation Matrix
| JSON Type | TypeScript Equivalent | Transformation Logic | Edge Case Handling |
|---|---|---|---|
| String | string | Direct Mapping | ISO Dates remain strings |
| Number | number | Direct Mapping | Int/Float unification |
| Boolean | boolean | Direct Mapping | Strict logical mapping |
| Object | interface | Modular Decomposition | PascalCase naming inference |
| Array | T[] | Generic Serialization | Union types for mixed arrays |
| Null | T | null | Union Promotion | Enforces runtime checks |
02 Interface Generation Pipeline
03 When You Reach for JSON → TS Generation
Generating types from JSON is a productivity multiplier in a narrow but very common band of work, onboarding to a new API, bootstrapping SDKs from documentation, or keeping client types in sync with an external schema you do not own.
-
Day one on a new third-party API Curl an example response, paste it here, get a starter interface in five seconds. You can refine optionality and discriminated unions later; the goal is to skip the manual interface-drafting tax and start coding against the shape immediately.
-
Library docs full of JSON examples When a vendor publishes JSON examples but no machine-readable schema (looking at you, half of REST docs in the wild), the fastest path to type-safe SDK code is to feed each example through a generator and combine the results.
-
Schema-to-type codegen sync For internal services, prefer authoritative codegen pipelines like
openapi-typescriptorquicktype --src-lang schema. This tool fills the gap when no schema exists yet, generate types first, write the schema afterward. -
Mock data → fixture types Drop a JSON fixture used in tests into the generator and get an interface that pins down its shape. Now your test data is typed and refactors break loudly instead of silently.
-
Quick interface reshape during refactors Two services exchange JSON; one side reshapes it. Paste the new shape, regenerate, replace the old interface, a 30-second update beats hand-editing nested optionals.
04 Worked Examples
[
{"id":"u_1","email":"a@x.io","phone":null},
{"id":"u_2","email":"b@x.io"}
]
interface User {
id: string;
email: string;
phone?: string | null; // optional AND nullable
}phone?: string means "the key may be missing"; phone: string | null means "the key is always present but value can be null". This payload exhibits both, so the generator emits ?: T | null. Conflating the two is the most common bug in hand-written interfaces, and the place where quicktype often defaults to one or the other.
{
"en-US": {"hello": "Hello", "bye": "Goodbye"},
"fr-FR": {"hello": "Bonjour", "bye": "Au revoir"},
"ja-JP": {"hello": "こんにちは", "bye": "さようなら"}
}Record, not a nested interface:type Translations = Record<string, Record<string, string>>;The "every key becomes an interface property" trap produces { "en-US": ..., "fr-FR": ..., "ja-JP": ... } hardcoded, useless the moment a new locale appears. Recognising a dictionary shape (homogeneous values, arbitrary string keys) and emitting Record<string, T> is the difference between a useful type and one you immediately delete.
type:[
{"type": "user.created", "userId": "u_1"},
{"type": "user.deleted", "userId": "u_1", "reason": "gdpr_request"},
{"type": "order.placed", "orderId": "o_42", "amount": 1299}
]type Event =
| { type: "user.created"; userId: string }
| { type: "user.deleted"; userId: string; reason: string }
| { type: "order.placed"; orderId: string; amount: number };A discriminated union lets TypeScript narrow types in switch (event.type). This is the canonical TS pattern quicktype often misses, it tends to merge all variants into a single interface with everything optional, losing the narrowing power.
05 Related Tools
Generated interfaces are erased at runtime. The tools below either pin types harder at compile time or add a runtime guard.
JSON to Zod
When you need runtime validation in addition to compile-time types, third-party APIs, webhooks, user input. Use z.infer<typeof Schema> as the single source of truth.
JSON Schema Validator
If your team already maintains JSON Schema, prefer json-schema-to-typescript or openapi-typescript over example-based generation, schema is the more authoritative source.
Code Explainer
Once the interface is generated, run it through the explainer to sanity-check optionals, unions, and Record shapes against how the API actually behaves.