JSON to TypeScript Interface Generator

Turn a JSON sample into export-ready TypeScript interfaces: nested objects become their own types, arrays become T[], and nulls fall back to any.

Typing API responses by hand is slow and easy to get wrong: a mistyped field name, a nesting level that gets skipped, an array that quietly becomes any[], and the compiler has nothing to check against. Paste a sample response and the interface definitions are written for you, with field names and nesting taken straight from the JSON. Copy the output into your project and trim it to fit.

The conversion runs in JavaScript in your browser, so neither the JSON nor the generated code is sent anywhere; samples from internal APIs are fine to paste. Keep in mind that this is inference from one static sample: arrays are read from their first element only, null can only fall back to any, and every field comes out required. Compare the result against the real contract before you rely on it.

Type inference rules

Strings, numbers and booleans map to string, number and boolean. null maps to any: a single value cannot tell you whether the field is always null or null for now, so the generator refuses to guess and does not mark the field optional either. An empty array becomes any[]. An array takes its element type from the first item only, so [1, "a"] produces number[] and the string type is dropped without warning; write (number | string)[] by hand when the data is genuinely mixed. JSON numbers are all doubles, so 1.0 and 1 are the same value and both produce number, and large integers such as snowflake IDs have already lost precision by the time JSON.parse returns — type those fields as string in your own code. Date strings stay string.

Nested types and naming

Every nested object becomes its own export interface. The name is the key with only its first letter capitalized, with no snake_case to PascalCase conversion, so user_profile yields User_profile and nested yields Nested. A key containing a hyphen, a dot or a space produces a type name that is not a valid identifier and has to be renamed after pasting. Only the first definition of a name is kept: if two branches both have a data key with different shapes, the second one reuses the first definition and its field types will be wrong. When the root is an array, the interface is built from the first element and an extra export type RootObjectList = RootObject[] is appended; a root primitive produces a single export type line. The root name comes from the Root type name field in the toolbar, defaulting to RootObject; anything that is not a letter, digit, underscore or dollar sign is stripped, so My-Type becomes MyType.

Field names and the generated file

Keys that are valid TypeScript identifiers are kept as they are. Keys with hyphens, dots, spaces or non-ASCII characters are emitted as quoted property names, which you then have to read with bracket notation such as row["user-name"]. Every field is required, there are no question marks, and a null value does not make a field optional, so the interface cannot express "this key may be absent" under strict mode. The output is read-only: copy it, or download it as json-to-ts.ts. The direction is one-way — converting TypeScript back to JSON would need a full language parser, which this tool does not have.

Advertisement

Frequently asked questions

Why does a null field become any instead of null or an optional field?
Because the value alone cannot tell you whether it is always null or temporarily null and actually another type. any accepts both and keeps the code compiling, at the cost of type safety: it is not a union with null, and the field is still required, so an object missing that key will not satisfy the interface. Replace it with the real type plus | null, and add a question mark if the key can be absent.
Why is the generated type wrong for an array with mixed elements?
Array element types come from the first item only. [1, "a"] becomes number[]; later strings neither widen the type nor produce a union. For genuinely mixed arrays, write (number | string)[] by hand, or keep any[] and narrow the values in your own code with a discriminant field.
Is the output interfaces or type aliases, and can I change the root name?
Objects generate export interface. A root array adds an export type alias for the list (RootObjectList by default) and a root primitive such as a bare number generates a single export type line. Type the name you want into Root type name in the toolbar: the default is RootObject, characters that cannot appear in an identifier are stripped, and an empty value falls back to the default.
Can I use the generated types as they are for a production API?
Treat them as a first draft. The output reflects one sample: keys missing from that sample do not appear, optional fields look required, arrays look homogeneous, and nulls are any. Rename the root type, fix the nullable and mixed-type fields, then diff the result against the API documentation — that review is what makes the types trustworthy.

Related tools

Advertisement