TanodTools

JSON to TypeScript

Turn a sample JSON document into TypeScript interfaces or type aliases, with optional fields and unions worked out from your data.

Runs entirely in your browser

TypeScript

    

Declare with
Modifiers

Types are inferred from the sample you paste, so they describe that sample and not a schema: a field that is a string in your example may be a number elsewhere. Numbers are all number, and dates stay string. Property order follows JSON.parse, which lists whole-number keys first.

How to generate TypeScript from JSON

  1. Paste a JSON response or file into the box. Several array items make the result better, because fields missing from some items become optional.
  2. Set the name of the top-level type, choose interface or type, and tick export, readonly or optional detection as needed.
  3. Copy the declarations or download them as a .ts file. Review the names, since they come from your key names.

Inferring types from a JSON sample

TypeScript types describe the shape of data, and a JSON response already contains a shape: each key, the kind of value behind it, and how objects nest. A converter walks through the sample and writes that shape down as declarations, so you do not have to type out forty fields by hand before you can call an API with confidence.

The step that matters most is what to do with arrays. Every item in an array of objects is read, and their shapes are merged: a key found in every item stays required, a key found in only some items becomes optional, and values that differ in kind become a union. That is why a sample with several records gives much better types than a sample with one. A value of null is treated differently from a missing key, because the two mean different things to code that reads the field.

Inferred types are a starting point, not a contract. They cannot know that a string is always one of three values, that a number is really an integer ID, or that a field that was present in all your examples can disappear in production. Read the result, rename anything that came out awkwardly, and tighten the types that matter.

Tips

  • Check that your sample is well-formed first with the JSON formatter, which points at the exact character of a syntax error.
  • Working with a YAML config instead? Convert it with YAML to JSON and paste the result here.
  • Need to look inside a token payload before typing it? Decode it with the JWT decoder.

Questions

How does it decide a field is optional?

When you have an array of objects, the objects are merged into one shape. A key that appears in some items but not all gets a ?. A key that is present but holds null in some items is not optional; it becomes T | null. Turn optional detection off if you would rather have every key marked required.

How are nested types named?

Each nested object is named from its key in PascalCase, so billing_address becomes BillingAddress. For an array, the item type drops a trailing "s" when the key is longer than 3 letters and does not end in ss, us or is: users gives User, while address gives AddressItem. If two different shapes want the same name, the second is numbered, giving User and User2.

What happens to objects with the same shape?

They share one declaration. If billing and shipping both hold { street, city }, you get one interface, named after the first place it appears. Two objects with the same keys but different value types are different shapes and get separate names.

Why is an empty array typed as unknown[]?

An empty array holds no examples, so nothing can be inferred about its items. unknown[] is the honest answer; change it by hand once you know the item type. An array that mixes values becomes a union, such as (string | number)[].

Can the output differ from the real API?

Yes. A sample shows only the values it contains. A field that is always present in your sample but sometimes missing in production will be required here, and an enum-like string will be plain string. For strict validation, use a schema; for a quick start, use this output and adjust it.

Is my JSON uploaded?

No. Nothing you paste is sent anywhere; the conversion runs in your browser, and you can disconnect from the network after the page loads.