Skip to content

TypeScript to JSON Schema — Numio

Generates a draft-07 JSON Schema from TypeScript types with ts-json-schema-generator. Every type goes under "definitions"; optional properties are left out of "required", and objects get "additionalProperties": false.

Your request and response types are TypeScript interfaces and you need JSON Schema for Ajv validation or an API gateway.

TypeScript

JSON Schema

When to use it

  • Your request and response types are TypeScript interfaces and you need JSON Schema for Ajv validation or an API gateway.
  • You want to publish a schema for a JSON config file whose shape is already defined as a TypeScript type.

How to use

  1. Paste TypeScript interfaces or type aliases. JSDoc tags such as @minimum, @format or @pattern are read into the schema.
  2. The source is posted to /api/typescript-to-json-schema, written to a temporary file on the server and processed with all types exposed.
  3. Copy the JSON Schema. If the input has only one type, the root also gets a $ref to it.

TypeScript

/** A product in the catalog */
export interface Product {
  /** @minimum 0 */
  price: number;
  name: string;
  tags?: string[];
}

JSON Schema (draft-07)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/Product",
  "definitions": {
    "Product": {
      "type": "object",
      "properties": {
        "price": {
          "type": "number",
          "minimum": 0
        },
        "name": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "price",
        "name"
…

Details and limitations

The page sends your input to a server route (/api/typescript-to-json-schema) for conversion; it is not processed only in the browser. Next.js API routes accept request bodies up to 1 MB by default.

JSDoc is parsed in extended mode: a description comment becomes "description", and tags like @minimum 0 or @minLength 1 become keywords.

Methods in interfaces are skipped. Date becomes a string with format date-time, and literal unions become enum.

bigint is not supported and returns an "Unknown node" error. Map and Set are described by their interface, an object with only a numeric size, so use Record<string, T> or arrays for JSON data.

FAQ

Are non-exported types included?

Yes. Every type in the input, exported or not, is added to "definitions", and references between them use $ref.

How are optional and nullable properties represented?

Optional properties are left out of "required". A union with null becomes anyOf with {"type": "null"}.

Why is there a $ref at the root?

With a single type the generator points the root at it with $ref. With several types, only "definitions" is output.

Specifications and references