JSON to TypeScript Generator
Paste, upload, or drag & drop JSON and get clean, production-ready TypeScript interfaces, types, classes, and enums instantly — with deep nested object/array support, smart optional and nullable field detection, union types, and Record<string, T> for dynamic keys. Nothing ever leaves your browser.
Convert JSON to TypeScript
Paste JSON, upload a file, or drag & drop — the TypeScript output updates live as you type or change options.
JSON Input
Generated TypeScript
How This JSON to TypeScript Generator Works
This tool first parses your JSON, then walks the resulting value and infers a structural shape for every object and array it finds — entirely in your browser, with no server round-trip. The interesting part isn't converting a single flat object (that's a one-to-one mapping); it's what happens with arrays of many objects, which is where most simple converters fall short.
What is JSON?
JSON (JavaScript Object Notation) is a lightweight, text-based data format built from objects (key-value pairs), arrays, strings, numbers, booleans, and null. It's the default format for REST APIs, configuration files, and data interchange between services — but it carries no type information at all: every consumer has to guess or document the shape of the data separately.
What is TypeScript?
TypeScript is a statically typed superset of JavaScript that adds interfaces, type aliases, enums, generics, and compile-time type checking. Interfaces and types describe the exact shape of a JSON payload, so your editor can autocomplete property names, and the compiler can catch a typo or a missing field before your code ever runs.
Why Convert JSON to TypeScript?
Manually writing an interface for a large or deeply nested API response is slow and error-prone — it's easy to miss an optional field, mistype a property name, or forget that a value is sometimes null. Generating the interface directly from a real JSON sample guarantees it matches reality, and updates in seconds when the API response shape changes.
Type Inference: Merging Shapes Across Array Items
When your JSON contains an array of objects, this generator doesn't just look at the first item. It infers a shape for every item and merges them: a field present in every item stays required; a field missing from at least one item becomes optional (?); a field whose value type differs between items (say, a number in one and a string in another) becomes a union type. This is what makes the output reflect the real variability of API data instead of just one lucky sample.
// Input
[
{ "id": 1, "name": "Ada", "email": "ada@example.com" },
{ "id": 2, "name": "Bob" }
]
// Output — "email" is optional because item #2 doesn't have it
export interface Root {
id: number;
name: string;
email?: string;
}
Nested Objects
Every nested object gets its own named interface, generated from the property path it was found at (for example, an address field becomes RootAddress). This keeps the output readable instead of collapsing everything into deeply inlined, unreadable object literals.
Nested Arrays & Arrays of Arrays
Arrays are typed based on their (merged) element shape: an array of strings becomes string[], an array of objects becomes OrderItem[] with a generated interface, and an array of arrays becomes a nested array type like number[][]. An empty array with no items to infer from becomes unknown[] so it still type-checks safely without you having to guess.
Optional vs. Nullable Properties
These are two different concepts this generator keeps distinct: optional (field?: T) means the key can be missing entirely; nullable (field: T | null) means the key is always present but its value can be null. Use the Null Handling setting to choose whether nullable fields become a union with null, get marked optional instead, or both.
Union Types & Literal Types
When a field's merged type set contains more than one primitive kind, or more than one distinct object shape that couldn't be merged, the output is a union type such as string | number. Enable Enum Detection and a repeated string field with a small set of distinct values (like a status field) becomes a string literal union — "active" | "inactive" | "pending" — or a named enum if you choose Named Enum instead.
Dynamic Keys & Record<string, T>
Some JSON objects use unpredictable keys as a lookup table — a map of user IDs to user records, for example — rather than a fixed set of named fields. With Detect Dynamic Keys enabled, an object with four or more keys that all look machine-generated (all-numeric, or all UUIDs) is generated as an index signature, Record<string, ValueType>, instead of one interface field per key.
// Input
{ "a1e4": { "score": 10 }, "b2f5": { "score": 20 }, "c3a6": { "score": 5 }, "d4b7": { "score": 8 } }
// Output
export interface Root {
[key: string]: RootValue;
}
export interface RootValue {
score: number;
}
Deduplicating Identical Shapes
Two structurally identical objects at different paths in your JSON — a billingAddress and a shippingAddress with the same fields, for instance — are detected as the same shape and generate one shared interface instead of two redundant copies, when Deduplicate Identical Shapes is enabled.
Empty Objects and Empty Arrays
An empty object ({}) with no observed keys becomes Record<string, unknown>, and an empty array becomes unknown[] — both are valid, safe TypeScript that won't silently allow any-typed access.
Interfaces vs. Types vs. Classes
All three declaration kinds this generator can output describe the same object shape — the right choice usually comes down to your codebase's existing convention rather than a hard technical requirement.
| Aspect | Interface | Type alias | Class |
|---|---|---|---|
| Best for | Object shapes, public APIs | Unions, primitives, composed types | Runtime instances, DTOs, decorators |
| Extending | extends, declaration merging | Intersection (&) | extends, implements |
| Runtime footprint | None — erased at compile time | None — erased at compile time | Real JS class, exists at runtime |
| Typical use here | Default choice for API responses | When you need unions/aliases too | NestJS DTOs, Angular models needing methods |
JSON vs. TypeScript
| JSON | TypeScript | |
|---|---|---|
| Purpose | Data interchange format | Typed superset of JavaScript |
| Type information | None — implicit only | Explicit interfaces, types, generics |
| Validated when? | Never, unless you add a schema validator | At compile time, by the TypeScript compiler |
| Editor support | None | Autocomplete, inline errors, safe refactors |
ToolAdda vs. QuickType vs. Transform.tools
| Feature | ToolAdda | QuickType | Transform.tools |
|---|---|---|---|
| Runs fully client-side | Yes | Yes (web version) | Yes |
| Merged optional/nullable inference | Yes, configurable | Yes | Limited |
| Record<string, T> for dynamic keys | Yes, automatic detection | Manual only | No |
| Enum / literal union detection | Yes, toggleable | Yes | No |
| Interface/type/class output | Yes, all three | Types and interfaces | Types only |
| Framework presets (React/Angular/Vue/NestJS) | Yes | No | No |
| No sign-up, no ads on the tool page | Yes | Yes | Yes |
Using Generated Types in React, Angular, Vue & Node
The generated interfaces drop straight into any TypeScript codebase. Here's how they're typically used across common frameworks and stacks.
import type { Root } from "./types";
function UserCard({ user }: { user: Root }) {
return <h2>{user.name}</h2>;
}
// Fetching and typing an API response
const res = await fetch("/api/user");
const user: Root = await res.json();
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Root } from './root.model';
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
getUser(): Observable<Root> {
return this.http.get<Root>('/api/user');
}
}
<script setup lang="ts">
import type { Root } from './types';
import { ref, onMounted } from 'vue';
const user = ref<Root | null>(null);
onMounted(async () => {
user.value = await (await fetch('/api/user')).json();
});
</script>
import express, { Request, Response } from 'express';
import type { Root } from './types';
const app = express();
app.get('/api/user', (req: Request, res: Response<Root>) => {
res.json({ id: 1, name: 'Ada', tags: ['admin'] });
});
import { Body, Controller, Post } from '@nestjs/common';
import { RootDto } from './root.dto';
@Controller('users')
export class UsersController {
@Post()
create(@Body() body: RootDto) {
return body;
}
}
Best Practices & Common Mistakes
Best Practices
- Generate types from a real API response, not a hand-written example — the auto optional/nullable detection is only as good as the sample data.
- Paste a few array items rather than just one, so the merge-based optional-field detection has something to compare against.
- Use a
DtoorResponsesuffix for API-facing types to keep them visually distinct from your internal domain models. - Turn on Readonly Properties for props and state you don't want accidentally mutated.
- Re-generate whenever the upstream API response shape changes, instead of hand-patching an old interface.
Common Mistakes
- Trusting a single sample too much — one API response won't reveal every optional or nullable field; use several examples if you can.
- Using
anyinstead of generated types — this defeats the entire purpose of TypeScript's compile-time checking. - Forgetting nested arrays of objects — always check that deeply nested interfaces were generated with sensible names before committing the output.
- Ignoring union types — a field typed
string | numberusually needs a runtime check before you use it, not a type assertion.
Large JSON Files & Performance
Conversion runs synchronously in your browser. For very large inputs (roughly 400KB and above), live conversion pauses automatically and waits for you to click Convert, so typing in the editor stays smooth instead of blocking on every keystroke.
Privacy & Security
Parsing, type inference, and code generation all happen inside your browser's JavaScript engine. No JSON or generated TypeScript is ever transmitted to ToolAdda's servers or any third party, which makes this safe to use even with sensitive API responses or internal data structures.
Frequently Asked Questions
What is a JSON to TypeScript generator?
A JSON to TypeScript generator analyzes a JSON object or array and produces matching TypeScript type declarations — interfaces, type aliases, classes, or enums — so you get compile-time type safety and editor autocompletion for that data shape instead of typing it out by hand.
How does the JSON to TypeScript generator work?
It parses your JSON, walks the resulting value recursively, and infers a structural shape for every object and array. When an array contains multiple objects, their shapes are merged so fields missing from some items become optional and fields with different value types become unions — then TypeScript code is generated from that merged shape.
Is my JSON data uploaded to a server?
No. Parsing, type inference, and code generation all run locally in your browser using JavaScript. Nothing you paste, upload, or drag and drop is ever sent to ToolAdda's servers.
Does it support nested JSON objects and arrays?
Yes. Nested objects become their own named interfaces or types, nested arrays become typed arrays of the inferred element type, and this works to any depth, including arrays of arrays and objects nested inside arrays inside objects.
Can it generate TypeScript interfaces?
Yes, interface is the default output. Choose Interface in the Declaration Type setting to generate a named interface for every distinct object shape found in your JSON.
Can it generate type aliases instead of interfaces?
Yes. Switch Declaration Type to Type to generate type X = { ... } aliases instead of interfaces — useful when you need to compose the result with union or intersection types elsewhere in your code.
Can it generate TypeScript classes?
Yes. Switch Declaration Type to Class to generate typed class field declarations, which is handy for frameworks like NestJS that use classes as DTOs and validation targets.
Does it support enums?
Yes, optionally. When a string field repeats across array items with a small, consistent set of values (like "active" | "inactive" | "pending"), set Enum Detection to String Literal Union for an inline union type, or Named Enum to generate a proper TypeScript enum instead.
What happens with null values in my JSON?
By default a field that is ever null becomes a union with null (for example city: string | null). Change Null Handling to Optional Field to mark it with a ? instead, or Both to apply both the union and the optional marker.
Does it support optional properties?
Yes. When Optional Field Detection is set to Auto (the default), a property is marked optional (?) automatically whenever it's missing from at least one object in a merged array of objects. You can also force every field to optional, or force every field to required.
Can I download the generated code?
Yes. Click Download .ts to save the generated TypeScript as a file, or Copy to copy it straight to your clipboard.
Is this JSON to TypeScript converter free?
Yes. It's completely free, has no usage limits, and requires no account or sign-up.
Does it work offline?
Once the page is loaded, all conversion logic runs in your browser's JavaScript engine with no network calls, so it keeps working even if your connection drops.
Does it support React projects?
Yes. Choose the React preset to generate readonly interfaces suited to typing props and API responses in React and Next.js components.
Can I use it with Angular?
Yes. The Angular preset generates interfaces with JSDoc hints, a good match for typing HttpClient responses and Angular services and models.
Does it support Vue?
Yes. The Vue preset generates plain interfaces that work directly with Vue 3's Composition API, defineProps, and TypeScript-based stores.
Can I customize interface and type names (prefix, suffix, root name)?
Yes. Set a custom Root Name for the top-level type, and an optional Prefix or Suffix (for example prefix "I" or suffix "Dto") applied to every generated interface, type, or class name.
Does it detect dates, UUIDs, emails, and URLs?
Yes, optionally. Enable JSDoc Format Hints and string fields matching an ISO date, date-time, UUID, email, or URL pattern get a /** @format ... */ comment above the field — the property type itself stays string, since TypeScript has no native date/UUID primitive.
Does it support generics like Record<string, T>?
Yes. Enable Detect Dynamic Keys and an object whose keys look machine-generated (all-numeric or all-UUID) is generated as Record<string, ValueType> — an index signature — instead of one interface per key.
Can I convert large JSON files?
Yes. Smaller and mid-sized files convert live as you type; very large inputs (roughly 400KB+) pause live conversion and wait for you to click Convert, so the browser tab stays responsive.
How are duplicate or repeated object shapes handled?
With Deduplicate Identical Shapes enabled (the default), two structurally identical objects anywhere in your JSON — even at different paths — generate a single shared interface instead of two separate, redundant ones.
What is the difference between interface and type in the generated code?
For the object shapes this generator produces, interface and type behave almost identically: both describe an object's properties. interface can later be extended or declaration-merged; type can be combined with unions and intersections and works for primitive/array aliases too. Pick whichever matches your codebase's existing convention.
Can JSON contain circular references?
No. JSON.parse cannot produce circular references — only JavaScript objects constructed at runtime can reference themselves — so circular-reference handling isn't applicable to a JSON to TypeScript conversion.
Does it support readonly properties?
Yes. Enable the Readonly Properties toggle to prefix every generated field with readonly, which is useful for immutable state, Redux/Zustand stores, and React props.
Can I generate NestJS DTOs?
Yes. The NestJS preset switches Declaration Type to Class and applies a Dto suffix, giving you a starting point for request/response DTO classes.
Related Developer Tools
Format, validate, minify, and sort JSON in your browser.
📄 JSON to YAML ConverterTurn JSON configs into clean, readable YAML.
📈 JSON to CSV ConverterConvert JSON arrays into spreadsheet-ready CSV.
🗂️ CSV to JSON ConverterTurn CSV spreadsheet data into structured JSON.
🔄 JSON to XML ConverterConvert JSON back into well-formed XML markup.
🔁 XML to JSON ConverterConvert XML markup into structured JSON.
🪪 JWT DebuggerDecode and inspect JSON Web Tokens for API debugging.
🆔 UUID GeneratorGenerate unique IDs for sample data and fixtures.
🔐 Base64 Encoder/DecoderEncode or decode Base64 strings and files instantly.
Ready to Generate TypeScript from Your JSON?
Paste, upload, or drop your JSON and get clean, ready-to-commit TypeScript interfaces, types, or classes in seconds — free, private, and built for real developer workflows.
⚡ Convert JSON to TypeScript Now