Skip to content
Kordu Tools
Developer Tools Runs in browser Updated 18 Apr 2026

JSON to TypeScript

Paste JSON and generate TypeScript interfaces or type aliases instantly. Handles nested objects, arrays, and nullables. Free, in-browser.

Root type

Root name

TypeScript
Loading rating…

How to use JSON to TypeScript

  1. Paste your JSON

    Paste a valid JSON object, array, or API response into the input. The parser validates on every keystroke and surfaces syntax errors inline with a line and column number so you can fix them without leaving the page.

  2. Fix any syntax errors

    If the parser reports an error, check for the common culprits: unquoted keys, trailing commas, single quotes around strings, or unescaped newlines inside strings. Valid JSON uses double quotes everywhere and no trailing commas.

  3. Choose interface or type alias

    Pick interface for traditional object shapes (supports declaration merging and extends) or type alias for more flexibility (supports unions, intersections, and mapped types). For most API-payload use cases, interface is the recommended default.

  4. Set the root type name

    Replace the default MyType with a PascalCase name that matches your domain model — User, Order, ApiResponse, InvoiceLine. Nested objects are auto-named from their parent key (address → Address).

  5. Generate and review the output

    The TypeScript appears instantly on the right. Scan it for over-generalization: fields that should be string literal unions (status, role), numeric fields that should be narrower, or optional properties that should be required once you confirm the full shape.

  6. Tighten types where needed

    Replace string with literal unions ('pending' | 'shipped') where the values are actually an enum. Add readonly to arrays you never mutate. Remove ? for fields you know are always present. Swap | null to just the base type if the API guarantees non-null.

  7. Copy into your project

    Click Copy to send the full generated block to your clipboard. Paste it into a types.ts, models/ folder, or alongside the fetcher that consumes the response. Re-run the tool any time the API shape changes and diff the output against the committed version.

JSON to TypeScript FAQ

What is the difference between an interface and a type alias?

Both declare the shape of an object. Interfaces support declaration merging (two 'interface User' blocks in the same scope fuse into one) and use 'extends' for composition. Type aliases are more flexible — they can represent unions, intersections, primitives, tuples, and mapped types. The TypeScript handbook recommends interfaces for public API surfaces and type aliases when you need the extra expressiveness.

Which should I pick — interface or type?

Default to interface for object shapes and public contracts — the error messages read more cleanly and declaration merging occasionally comes in handy. Reach for type aliases when you need unions ('idle' | 'loading' | 'error'), intersections, mapped types, conditional types, or when you're aliasing a primitive. For generated API types, interface is almost always the right call.

How are nested objects handled?

Nested objects are promoted to their own named interfaces rather than inlined. A key 'address' with an object value generates a separate 'Address' interface, and the parent uses 'address: Address'. This keeps types reusable, shrinks the noise at each nesting level, and makes the output readable at any depth.

How are arrays typed?

Arrays become T[] where T is inferred from the elements. If every element has the same shape, you get a simple element type (string[], User[]). If elements vary, the generator emits a union element type such as (string | number)[] or (User | Admin)[] so no element is silently cast to any.

What happens with mixed-type arrays?

Mixed-type arrays generate a union element type — for example, ['a', 1, true] becomes (string | number | boolean)[]. Mixed object arrays unify into a union of the inferred object shapes, which you can refine into a discriminated union by adding a shared 'type' or 'kind' field.

How are null values handled?

Properties that are null in the sample default to optional plus nullable: field?: T | null. JSON can't distinguish 'missing key' from 'key present with value null,' so the generator picks the most permissive interpretation. Tighten to 'field: T | null' (always present, sometimes null) or plain 'field: T' (never null) once you confirm the API contract.

Can I paste a JSON Schema instead of a JSON sample?

No — this tool infers types from a JSON instance, not from a JSON Schema. For JSON Schema → TypeScript, use json-schema-to-typescript or Ajv's type-generation. For OpenAPI specs, use openapi-typescript, which generates the full client and types from the spec.

Does it generate Zod, Valibot, or Yup schemas?

No — it generates TypeScript type declarations only, not runtime validators. If you need runtime validation at the API boundary, pair the generated interface with a hand-written or machine-generated Zod or Valibot schema. Libraries like quicktype and ts-to-zod can convert the generated type into a Zod schema.

Is there a size limit on the JSON input?

Parsing runs in your browser, so the practical limit is your device's memory — tens of megabytes of JSON work fine on a modern laptop. For truly massive payloads (a full-dump API response), consider trimming to a representative sample before pasting. There is no server-side upload and no rate limit.

Can it detect string enums?

Not from a single sample. A field with value 'pending' is typed 'string' because there is no way to know whether other responses also use 'shipped' or 'delivered'. After generation, manually narrow the field to a string literal union: status: 'pending' | 'shipped' | 'delivered'. Multi-sample tools like quicktype can infer enums when given several examples.

Does it support JSONC (JSON with comments)?

Not directly — strict JSON.parse rejects comments. Strip // and /* */ comments before pasting, or run the input through a JSONC parser first. The JSON spec itself has never allowed comments; JSONC is a VS Code convention for config files.

How does it handle circular references?

JSON itself cannot represent circular references (JSON.stringify throws on cycles), so circular JSON never reaches the tool. If you need recursive types in TypeScript — a tree node with child nodes of the same shape — add the recursion manually after generation: interface TreeNode { value: string; children: TreeNode[]; }.

What if a field is sometimes missing from the response?

Generate from a sample where the field is present, then manually mark it optional (field?: T) in the output. A single sample can't tell the generator whether a missing key is 'always absent' or 'sometimes absent.' If you have multiple samples that differ in which keys are present, quicktype handles optional inference natively.

How does this compare to quicktype?

Kordu's generator is optimized for the common case: one JSON sample, instant output, no install, runs in-browser. Quicktype is more powerful when you have multiple samples to unify, want to generate other languages (Go, Rust, Swift, C#), or need JSON Schema input. Use Kordu for quick single-sample inference and quicktype for larger cross-language type-generation workflows.

Is my JSON data sent anywhere?

No. All parsing, inference, and code generation run entirely in your browser. Nothing you paste is uploaded, logged, or stored — the generator is pure client-side JavaScript and works offline once the page has loaded. Safe to paste production payloads, tokens redacted.

Background

The Kordu JSON to TypeScript converter generates TypeScript type definitions from any JSON sample you paste in. Instead of hand-writing interface User declarations from a Swagger response or a dumped fetch payload, paste the JSON and get a ready-to-use interface or type alias in under a second — with nested objects promoted to named types and array elements unified into a single, accurate element type.

Why typing your JSON matters

TypeScript types are the contract between the data your application receives and the code that consumes it. When an API returns JSON without a typed definition, every consumer either casts to any (giving up type safety entirely) or duplicates an ad-hoc shape inline. Both paths break during refactors: a field renamed server-side slips past the compiler, autocomplete stops suggesting real properties, and every field access becomes a runtime gamble. A generated interface gives you compile-time detection of shape drift, IDE autocomplete for every nested field, safer refactors across large codebases, and readable documentation of the payload in a single file.

How the generator infers types

The tool walks the parsed JSON tree depth-first. Each object node becomes a named interface — the root uses the name you provide (default MyType), and nested objects derive their names from the parent key (user.addressAddress). Primitive leaves map to string, number, boolean, or null. Arrays are scanned; if every element has the same inferred shape, the array becomes T[], and if elements differ (for example a mix of string and number, or two different object shapes), the generator emits a union element type such as (string | number)[]. Keys that are not valid JavaScript identifiers (hyphens, dots, numeric prefixes, spaces, reserved words) are auto-quoted so the output compiles without manual fix-ups.

Interface vs type alias

Both declare object shapes, but they have different superpowers. Interfaces support declaration merging (two interface User blocks in the same scope fuse into one), use extends to compose hierarchies, and are the TypeScript handbook's preferred default for public API surfaces because their error messages read more cleanly. Type aliases (type User = { … }) can express things interfaces cannot: unions (Status = 'idle' | 'loading'), intersections (Admin & Paging), mapped types, tuple types, and aliases for primitives. Rule of thumb: use interface for object shapes and public contracts; reach for type when you need unions, mapped types, or conditional types. The tool lets you pick either and switch later — the emitted structure is identical.

Naming conventions that age well

Generated types read better when you apply a consistent naming scheme across the project. Use PascalCase for every type (Order, not order or IOrder — the I prefix is a C#-ism TypeScript style guides have moved away from). Name item shapes in the singular (OrderLine, not OrderLines) so OrderLine[] reads naturally. For API payloads, a common pattern is ApiResponse<T> as an envelope and User, Order, or InvoiceLine for domain entities inside it — keep domain types separate from transport types so you can swap REST for GraphQL without renaming.

Handling real-world API responses

Production APIs rarely return bare objects. REST endpoints usually wrap the payload ({ data, pagination, meta }), pagination cursors add envelope noise, and error branches return a different shape entirely. Generate the type from a real successful response — include the envelope — and then extract only the inner types your UI actually consumes (User from ApiResponse<User>). Re-exporting every generated type from a public barrel is a common anti-pattern: it leaks transport shapes into business code and forces every downstream rename into a breaking API change.

Nullable vs optional

TypeScript has three related concepts that JSON flattens into one. An optional property (age?: number) means the key may be missing. A nullable property (age: number | null) means the key is present but may be null. A property typed number | undefined is again optional but noisier. Since JSON samples don't distinguish "missing" from "explicitly null," the generator defaults to field?: T | null when it sees null in the sample — the most permissive interpretation. If you enable exactOptionalPropertyTypes (TS 4.4+), tighten the generated type by removing ? when you know the field is always present, and remove | null when the API guarantees it.

What inference can and cannot do

A single JSON sample is a snapshot, not a schema. The generator infers exactly what it sees: a field that happens to be null in your sample will come through as nullable, even if the API also returns strings. A numeric field will be typed number — TypeScript has no integer type, and JSON doesn't either. String fields will be typed string even when the values are clearly an enum ("pending" | "shipped" | "delivered"). Inference cannot detect semantic formats (email, URL, UUID, ISO date) or discriminated unions without multiple samples. Treat the output as a strong starting draft — tighten the literal unions, narrow string to template literal types where it adds value, and add readonly to arrays you never mutate.

Limitations and when to reach for a schema tool

If you have multiple samples of the same endpoint, quicktype (the de-facto multi-sample inference tool) unifies them into a single type more accurately than any single-sample tool can. If you need runtime validation — parsing an unknown API response and rejecting malformed payloads at the boundary — pair the generated interface with a Zod or Valibot schema, or use Ajv with a JSON Schema. For OpenAPI specs, openapi-typescript generates the full client from the spec. The Kordu generator is the fastest path from "I have a JSON example" to "I have a working TypeScript type," not a substitute for those stronger approaches when you need them.

Compared to writing types by hand

Hand-writing types from a JSON example is mechanical, error-prone, and scales badly: a 40-field User object takes 10 minutes to type, and every typo sits latent until it causes a bug. The generator is deterministic, handles nested structures correctly on the first pass, and enforces consistent naming. Paste, review, copy — ten seconds instead of ten minutes.

Privacy and data processing

All parsing, inference, and code generation happens entirely in your browser. Kordu does not upload, log, or store your JSON. There is no backend — the generator is pure client-side JavaScript, which means it works offline once the page has loaded, handles sensitive payloads safely, and has no rate limits or signup walls.