glunty

JSON to TypeScript Interface

Generate TypeScript interfaces from a JSON sample. Pure client-side.

What this tool does

Reads a JSON document and emits one or more TypeScript interface declarations that describe its structure. Nested objects become their own interfaces with names derived from their property names. Arrays of objects are typed as the array of the generated nested interface. Mixed-type arrays produce union types. Empty arrays become unknown[]. Null values become null so you can decide whether to mark the field optional. Generation is local; your JSON never leaves the browser.

How to use it

Paste JSON into the input. Set the root interface name (defaults to Root). Toggle Export interfaces on if you want export interface instead of plain interface. Press Convert. Example: a JSON object with id, name, and a nested address object produces a Root interface plus an Address interface, both ready to paste into a .ts file.

Common use cases

  • Bootstrapping types for a third-party API where you have a sample response but no published schema.
  • Quickly typing fixtures or mock data for a test suite.
  • Reading a JSON config and getting auto-completion on its keys in your editor.
  • Converting an example payload from API documentation into a TypeScript starting point.
  • Spotting field-name typos by seeing them as a strict type.

Common pitfalls

  • One sample is not the schema. The output reflects the structure of the specific JSON you paste. If a field is missing from your sample but exists in real data, the type will not include it. Mark uncertain fields as optional (add a ? after the name) before relying on the type.
  • Nullable vs missing. A field with null in your sample becomes null-typed. A field that is sometimes absent should be marked optional with ?. JSON cannot express the difference; you decide based on the API contract.
  • Date strings. JSON has no native date type, so dates appear as strings. The generated interface types them as string. Add a narrower type (e.g., a branded string) by hand if your codebase distinguishes date strings from arbitrary strings.

Frequently asked questions

How is one JSON sample sufficient to derive types?
It is not sufficient on its own. The output reflects exactly the structure of the JSON you paste. Fields missing from your sample do not appear in the type, and fields that are sometimes nullable but present-and-non-null in the sample become non-nullable. Treat the output as a starting point. Mark uncertain fields optional with ?, and consider running multiple representative samples through the tool to compare.
Why is a field marked as null instead of optional?
JSON cannot distinguish "the key is present with value null" from "the key may sometimes be absent." If your sample shows null, the output types it as null. If a field can be absent, mark it optional manually by adding ? after the name (email?: string). The two are different in TypeScript: optional means may be undefined, null-typed means present but null.
How are mixed-type arrays handled?
An array containing both strings and numbers becomes (string | number)[]. The tool reads each element, collects the union of element types, and emits the union as the array element type. Empty arrays type as unknown[] since there is no element to read. Mixed-type arrays often suggest a poorly-modeled API; consider whether the source should be normalized before consuming.
Why are nested objects extracted into separate interfaces?
Top-level interfaces are easier to read, reuse, and refactor than deeply nested inline types. The tool gives each nested object its own interface named after the property it lives under (capitalized to PascalCase). If two nested objects share the same property name but have different shapes, the second gets a numeric suffix (Address, Address2, etc.).
Does this output match what zod or io-ts would generate?
No. zod and io-ts generate runtime validators, not just static types. They additionally check at runtime that incoming JSON matches the expected shape. This tool only emits the static interface declaration, which the TypeScript compiler enforces at compile time but cannot verify against actual API responses. For runtime safety, generate the type here, then add a zod or io-ts schema by hand.
Why are number types generic and not literal?
A field with the value 42 in your sample could be any integer in real data. The tool types it as number. If you know a field is constrained (a status code 0-9, a discriminant value), narrow the type by hand: status: 200 | 404 | 500 instead of status: number. The tool prefers correctness over over-specification.

Embed this tool

Free for any use; attribution appreciated. Paste this on your site:

The embed runs the same tool that lives at this URL. No tracking; no ads inside the embed. Resize height as needed for your layout.

Cite this tool

For academic, journalistic, or technical references. Pick a format:

Citations use 2026 as the publication year. Access date is left as a fillable placeholder where the citation style expects one.

Embedded tool from glunty.com