TypeScript Type Generator
Paste JSON and get TypeScript interfaces instantly — nested types, arrays, optional fields, union types, and readonly modifiers.
Options
Indent size
Declaration style
Your API returns a 30-field JSON response and you need TypeScript interfaces for type-safe access. The JSON to TypeScript tool on PureDevTools handles this — but this generator adds union type inference from arrays of objects, readonly property detection, and type alias vs interface output modes. Paste the JSON, get the types.
Why This Generator (Not the JSON to TypeScript Tool)
PureDevTools has a JSON to TypeScript converter focused on interface generation with optional properties and export keywords. This generator adds advanced inference — union types from heterogeneous arrays, readonly detection, and a choice between type aliases and interface declarations. Use the JSON-to-TypeScript tool for standard interface generation; use this generator when you need more control.
What Is the TypeScript Type Generator?
The TypeScript Type Generator converts JSON data into TypeScript type definitions with one click. Paste any JSON object or array, configure your preferences, and get ready-to-use interface or type declarations — including proper nesting, array types, optional fields, union types, and readonly modifiers.
No TypeScript compiler required. All processing happens in your browser.
What Is a TypeScript Interface?
A TypeScript interface describes the shape of an object: which properties it has, what types those properties hold, and whether they are optional or required.
interface User {
id: number;
name: string;
email: string;
active: boolean;
}
Any object that matches this shape satisfies the User type. TypeScript checks this at compile time, catching property name typos, wrong value types, and missing required fields before your code runs.
Interface vs. Type Alias
Both interface and type can describe object shapes. The generator supports both:
| Feature | interface | type alias |
|---|---|---|
| Object shapes | Yes | Yes |
| Extending | extends keyword | Intersection (&) |
| Declaration merging | Yes (same name declared twice = merged) | No |
| Primitives/unions at top level | No | Yes |
| Generally preferred for | Public APIs, class contracts | Unions, intersections, mapped types |
Use interface when describing the public shape of a class or API response. Use type when you need unions, intersections, or when you want to prevent accidental declaration merging.
The generator defaults to interface because it is the idiomatic choice for data shapes, but the type alias option produces identical runtime behavior.
How the Generator Works
The generator performs a recursive depth-first traversal of the parsed JSON:
- Primitive values (
string,number,boolean,null) map directly to their TypeScript equivalent. - Nested objects become separate named type definitions. The type name is derived from the property key using PascalCase conversion (
address→Address). - Arrays inspect all elements to determine the element type. Homogeneous arrays produce
string[],number[], and so on. Arrays of objects merge all element shapes into a single named element type, making fields that are absent in some elements optional. - Mixed arrays produce union element types:
(string | number)[]. - Name conflicts are resolved automatically by appending a counter suffix (
Address2,Address3).
The root type is always placed first in the output, followed by its nested types in declaration order.
Generated Output Example
Input JSON:
{
"user": {
"id": 1,
"name": "Alice",
"roles": ["admin", "editor"],
"address": {
"city": "New York",
"zip": "10001"
}
},
"posts": [
{ "id": 1, "title": "Hello", "published": true },
{ "id": 2, "title": "World", "published": false }
]
}
Generated TypeScript (default options):
export interface Root {
user: User;
posts: Post[];
}
export interface User {
id: number;
name: string;
roles: string[];
address: Address;
}
export interface Post {
id: number;
title: string;
published: boolean;
}
export interface Address {
city: string;
zip: string;
}
Generator Options Explained
Root Type Name
The name for the top-level type. Defaults to Root. Use a descriptive name that matches your domain: ApiResponse, UserProfile, ProductCatalog. The name is converted to PascalCase automatically.
Declaration Style: interface vs. type alias
Controls whether the generator emits interface Foo { ... } or type Foo = { ... };. Both are semantically equivalent for plain object shapes.
Export Types
Prepends export to every generated declaration. Enable this when pasting the types into a module you intend to import elsewhere. Disable it for type declarations inside a .d.ts file that uses declare global.
Readonly Properties
Adds the readonly modifier to every field:
export interface Config {
readonly host: string;
readonly port: number;
}
Use this for configuration objects, value objects, and any data that should never be mutated after construction. TypeScript will raise a compile error if code tries to assign to a readonly property.
Make All Optional
Appends ? to every field, making all properties optional:
export interface PartialUser {
id?: number;
name?: string;
email?: string;
}
Useful when generating types for PATCH request bodies, form state, or any scenario where partial data is valid. In a merge of array elements, fields absent from some elements are already marked optional automatically; this option forces all fields to be optional regardless.
Indent Size
Controls the indentation of property lines inside type declarations: 2 spaces (default) or 4 spaces.
Handling Special Cases
null Fields
JSON null maps to the TypeScript null type:
interface Response {
data: Data;
error: null;
}
In practice you would often use null | string for error fields. The generator produces the literal type based on the value observed in the sample JSON.
Arrays of Mixed Objects
When array elements have different keys, the generator merges all shapes into one type. Fields present in every element are required; fields present in only some elements are marked optional:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "role": "admin" }
]
Generates:
export type Root = Item[];
export interface Item {
id: number;
name?: string;
role?: string;
}
Property Keys With Special Characters
Keys that are not valid JavaScript identifiers (containing hyphens, spaces, or starting with a digit) are automatically quoted:
export interface Headers {
"content-type": string;
"x-api-key": string;
"0": string;
}
Using Generated Types in Your Project
Copy the output and paste it into a .ts file. To use the types:
import type { Root, User, Post } from "./types";
const response: Root = await fetchData();
console.log(response.user.name); // TypeScript knows this is a string
For API responses, add the types to a src/types/api.ts file and re-export them. For configuration files, inline them next to the configuration constants.
Frequently Asked Questions
What is the difference between interface and type in TypeScript?
Both describe object shapes and are interchangeable in most situations. interface supports declaration merging (two declarations with the same name are merged into one) and is preferred for public API contracts. type supports union types, intersection types, and mapped types, making it more flexible but unable to be merged.
Why are some fields marked as optional (?) in array element types?
When multiple array elements have different keys, the generator marks keys that do not appear in every element as optional. For example, if element 1 has a role field but element 2 does not, role becomes role?: string. This accurately reflects that the field may or may not be present at runtime.
Can I generate types from a JSON array at the root level?
Yes. If your JSON starts with [, the generator creates a type alias for the root array and a separate interface for the element shape. For example, a root JSON array produces export type Root = Item[]; with a corresponding Item interface.
How should I handle null vs. undefined in TypeScript?
TypeScript distinguishes between null (explicitly set to no value) and undefined (not set). JSON only has null; undefined is a JavaScript-only concept. The generator uses null when the JSON value is null. Add | undefined manually to fields that may be absent in some contexts.
What does the readonly modifier do at runtime?
Nothing. readonly is a TypeScript compile-time constraint only. At runtime, objects behave as normal JavaScript objects. Use readonly to communicate intent and let the TypeScript compiler catch accidental mutations during development.
Is my JSON data sent to a server?
No. All parsing and type generation happens entirely in your browser using JavaScript. No data is transmitted to any server. Your JSON stays completely private.