Why generate TypeScript from JSON instead of writing it by hand#
Most typed frontends and Node services spend their first hours on a new integration copying a sample response from the network tab and translating it into interfaces. That busywork is easy to get wrong: a nested object forgotten, an array typed as any[], a field that is sometimes missing left required. Generating declarations from a real payload gives you a structural starting point that matches the data you actually received.
This converter is meant for that paste-and-ship moment. It does not call a server, does not require an account, and does not invent runtime validators. You get plain TypeScript interfaces or type aliases you can refine — rename fields, narrow string unions, swap null for undefined — once the shape is in your repo.
Interfaces vs types, nested names, and the export keyword#
Both interface and type aliases describe object shapes in TypeScript. Interfaces are often preferred for public object contracts because they merge declarations and read clearly in error messages; type aliases are required when the root value is an array or a primitive, and are handy when you want a union or mapped type later. Pick the style your codebase already uses — the inferred fields stay the same.
Every nested plain object becomes its own PascalCase declaration, referenced by name from the parent. That keeps deep JSON readable instead of inlining huge anonymous objects. The export toggle prefixes every declaration with export so you can drop the block into a module and import Root elsewhere; turn it off for file-local types.
How arrays and nulls become optional fields#
When a property holds an array of objects, the converter merges every item into one declaration. Keys that appear on some items but not others are marked optional with ?. That mirrors real API lists where later pages or newer records add fields. Empty arrays become unknown[]; mixed primitive arrays become a union element type such as (number | string)[].
Null is a value TypeScript models explicitly. With optional nulls enabled (default), a field whose sample value is null is emitted as optional (tagline?: null) so you are nudged to widen it when you know the non-null type. When the same key is sometimes a string and sometimes null across array items, the merge becomes string | null and stays optional under that setting. Disable the toggle if you want literal null kept required for documentation samples.
What this tool does not emit (classes, Zod, runtime checks)#
Search queries like “json to typescript class” often expect Java-style classes with constructors. TypeScript projects almost always want structural interfaces or type aliases for JSON — classes add prototype baggage you do not need for plain data. By default this tool emits interfaces or types only, not classes. If you need runtime validation, pipe the same JSON into a schema generator or write Zod/io-ts by hand on top of these types.
Inference is only as good as the sample. A field that is always a string in production but null in your fixture will look like null here. Prefer a representative payload (or several array items) before locking types into a shared package. For formatting or validating the JSON itself first, use the JSON formatter on this site, then paste the cleaned document here.