JSON to TypeScript Converter
Turn JSON or JSON Lines samples into TypeScript declarations with configurable null and optional-property policies plus array inference and runtime guards.{{ values.types_code }}
{{ values.guard_code }}
| Path | Inferred type | Presence | Evidence | Copy |
|---|---|---|---|---|
| {{ row.path }} | {{ row.type }} | {{ row.status }} | {{ row.evidence }} |
| Priority | Area | Evidence | Next check | Copy |
|---|---|---|---|---|
| {{ row.level }} | {{ row.area }} | {{ row.evidence }} | {{ row.action }} |
A JSON sample often arrives before the contract that will govern it. It may be one API response, several event records, or a saved fixture. TypeScript declarations can give that data a useful shape, but they describe what the sample suggests rather than proving what every future message will contain.
The easy mappings are direct: JSON strings become string, numbers become number, booleans become boolean, objects become named object types, and arrays become item collections. The important decisions sit around missing evidence. A property absent from one record is different from a property present with null, and an empty array gives no evidence about its item type.
| Sample evidence | Reasonable declaration | What still needs review |
|---|---|---|
| A key appears in every sampled object | Required property | A larger production sample may still omit it. |
| A key is absent from some objects | Optional property | Absence may be accidental or version-specific. |
A value is sometimes null | Nullable union | Null and a missing property are not interchangeable. |
| An array contains mixed value kinds | Union item type | Mixed data may indicate an upstream inconsistency. |
| An array is empty | Configured fallback item type | No sample establishes the real item type. |
Arrays need a second judgment. A normal list can merge evidence from all sampled items, while a tuple says that each position has a stable meaning. Repeated short arrays are not automatically tuples; position must be part of the real data contract.
Type declarations disappear when TypeScript is compiled, so they do not make untrusted JSON safe at runtime. Generated declarations should be compared with API documentation, schema files, tests, and a broader set of real records. Exact identifiers are another common trap: a JSON integer outside JavaScript's safe integer range may already have lost precision before a type declaration can describe it.
How to Use This Tool:
Start with representative data, then choose policies that match the contract you intend to maintain.
- Enter a meaningful Root type name, then paste one complete JSON value or several JSON Lines records into Representative source.
- Choose Input format. Auto detect accepts a complete JSON value first; if that fails, every nonblank line must be valid JSON for the source to be treated as JSON Lines.
- Set Missing properties, Null handling, and Array inference from the contract you want, not simply from the smallest sample that happens to be available.
- Choose interface or type-alias declarations and the emit mode used by the destination project. Turn on readonly fields or alphabetical sorting only when those conventions belong in the generated source.
- Review Generated types beside the Inference ledger and Review notes. Correct invalid JSON, investigate ambiguous paths, and test the runtime guard before adopting the declarations.
Interpreting Results:
The generated declarations are a draft contract. Required and optional markers are only as trustworthy as the object samples behind them, while unions show every observed value kind rather than which kinds the upstream system promises.
- Use the Inference ledger to see the presence evidence and inferred type for each path.
- Treat Review notes as unresolved decisions, especially for empty arrays, null-only values, literal unions, and unsafe integers.
- Use the runtime guard as a first-pass shape check. It verifies the root kind and observed top-level property kinds, not complete nested semantics, formats, numeric ranges, or business rules.
Technical Details:
JSON supplies six value kinds: object, array, string, number, boolean, and null. Type inference walks that value tree, collects evidence at each path, assigns names to object shapes, and then renders declarations from the selected policies. Property order follows the first observed object unless alphabetical sorting is selected.
Transformation Core
The conversion is deterministic for the same sample and settings. The governing stages are:
| Stage | Rule | Material consequence |
|---|---|---|
| Parse | Read one JSON value, or parse every nonblank JSON Lines row and treat the rows as one array sample. | A single bad JSON Lines row rejects the source. |
| Collect | Group values by object path and count property presence across the sampled objects. | Missing-property policy decides whether ? is emitted. |
| Infer | Map observed kinds, merge array items or infer a fixed tuple, and apply null and fallback policies. | Mixed kinds become unions; empty evidence uses unknown, any, or never. |
| Name | Create safe PascalCase declaration names and quote property keys that are not TypeScript identifiers. | Nested object paths receive distinct names when needed. |
| Render | Emit interfaces or type aliases, with export, ambient, or namespace syntax. | Declaration style changes syntax, not the inferred evidence. |
| Check | Build a runtime predicate from the root shape and its observed top-level fields. | The predicate is intentionally narrower than full schema validation. |
For two records such as {"id":1,"nickname":null} and {"id":2}, the default policies retain id: number and make nickname optional because it is missing from one object. Its observed null does not establish a non-null value type, so the selected null and fallback policies determine the final declaration. Adding a representative non-null nickname provides the missing evidence.
Policy boundaries and limits
- Literal string unions are considered only for two to eight repeated values and are withheld for date-, email-, URL-, or UUID-like strings.
- Tuple inference applies only when every sampled array has the same length from 1 through 8; otherwise item evidence is merged into an array type.
- Input is limited to 200,000 characters, uploaded files to 2 MiB, nesting to 32 levels, sampled fields to 2,500, and named declarations to 250.
- Date, email, URL, and UUID patterns remain
string. Recognition creates a review note rather than a branded runtime type. - Displayed counts describe the supplied sample. They are not coverage percentages for the production data set.
Privacy Notes:
Conversion runs in the current browser tab and does not require sending the pasted JSON to a conversion service. That makes local review possible, but copied output and downloaded files can still contain names, identifiers, or sample values.
- Use redacted representative records when production payloads contain personal data, tokens, or internal identifiers.
- Inspect generated comments, review evidence, and guard messages before sharing the output outside the project.
Worked Examples:
Several API records
Three JSON Lines records share id and status, while only one contains discountCode. With merged arrays and optional-if-missing selected, the root becomes an array type and discountCode is optional. The ledger should show presence in one of three object samples, which is the evidence to confirm against the API contract.
An empty collection
The sample {"tags":[]} produces tags: unknown[] with the safe fallback. The review note is more important than the syntactically valid declaration: add a sample containing a real tag or replace the fallback with the documented item type before relying on it.
References:
- RFC 8259: The JavaScript Object Notation Data Interchange Format, IETF, December 2017.
- TypeScript Handbook: Object Types, Microsoft.
- How to configure TypeScript for Node.js, Simplified Guide.