JSON Schema to TypeScript
Generate TypeScript interfaces from a JSON Schema document.
Related Tools
Generate a JSON Schema (Draft 2020-12) from a JSON document.
Generate TypeScript interfaces or type aliases from JSON.
Validate JSON against a JSON Schema with JSON-pointer error paths.
Generate Go structs with JSON tags from a JSON document.
Generate Python dataclasses from a JSON document.
Generate a Zod validation schema and TypeScript type from a JSON document.
Documentation
What is JSON Schema to TypeScript?
This tool reads a JSON Schema document and generates the equivalent TypeScript interface/type declarations — the reverse of JSON to JSON Schema. Unlike that tool, which infers a schema from one sample and necessarily guesses at edge cases, this direction is a direct structural translation: a JSON Schema already states its types, required fields, and enums explicitly, so there's no inference involved for the parts of the schema this tool supports.
How it works
Named types under $defs (Draft 2020-12) or definitions (Draft 07 and earlier) each become their own export interface or export type, with the def's key PascalCased into a type name. A $ref anywhere in the schema resolves to that type name directly rather than inlining the referenced schema's body, so the output mirrors the schema's own structure instead of flattening it. type: "object" with a properties map becomes an interface, with each property optional (?) unless it's listed in that object's required array; type: "array" with items becomes T[]; an enum becomes a union of string/number literal types; and oneOf/anyOf become a union of each branch's translated type.
Features
- Supports both
$defs(2020-12) anddefinitions(Draft 07) $refresolved to a named type reference, not inlinedenum→ TypeScript literal uniononeOf/anyOf→ TypeScript union type- Unsupported constructs (
allOf,patternProperties, conditional schemas) flagged in a comment rather than silently approximated
Example
Input:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "#/$defs/User",
"$defs": {
"User": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"role": { "enum": ["admin", "member"] }
},
"required": ["id", "name"]
}
}
}Output:
export interface User {
id: number;
name: string;
role?: "admin" | "member";
}
export type Root = User;Common errors
A schema built with allOf to merge several base schemas together won't produce a full intersection type — only the first branch is used, and a comment at the top of the output says exactly that, since silently unioning or picking-and-hoping would produce a type that looks plausible but is wrong. The same honesty applies to patternProperties (regex-matched property names have no TypeScript index-signature equivalent this tool generates) and conditional if/then/else schemas — both are named explicitly in the output comment rather than approximated.
Best practices
If your schema uses allOf for composition, check the generated type against the full schema by hand — merging the branches yourself (usually with an & intersection type) is usually a small, mechanical fix once you know it's needed, which is exactly why the tool flags it instead of guessing.
Frequently Asked Questions
Does this support Draft 07 schemas, or only 2020-12?▾
Both — the parser reads named types from either $defs (2020-12) or definitions (Draft 07/04), whichever the schema uses, and resolves $ref pointers into either one the same way.
What happens to oneOf / anyOf?▾
Each becomes a TypeScript union type (A | B | C). allOf is different — TypeScript has no direct "merge these schemas" operator that matches JSON Schema's allOf semantics exactly, so only the first branch is used, and a comment at the top of the output says so explicitly rather than silently producing an incomplete intersection.
What about patternProperties or conditional (if/then/else) schemas?▾
Neither has a clean TypeScript equivalent, so neither is translated — only the explicit keys under "properties" become fields, and any if/then/else conditional is ignored in favor of the schema's base type. Both omissions are called out in a comment at the top of the generated code.
How are required vs optional properties handled?▾
A property listed in the schema's "required" array becomes a non-optional field; everything else gets a ? — the standard TypeScript convention, and the exact inverse of what JSON to JSON Schema does when inferring required fields from a sample.