bcherny / json-schema-to-typescript

Compile JSON Schema to TypeScript type declarations
https://bcherny.github.io/json-schema-to-typescript-browser/
MIT License
2.92k stars 392 forks source link

Code generation for array of objects is wrong #532

Open avishaybp81 opened 1 year ago

avishaybp81 commented 1 year ago

I have 2 json schema.

Elephant declare array of dogs and I am expecting the generated code to reflect that. However I don't get array of dogs in the generated TS code.

How can I get array of Dog in the generated code?

types.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "Dog": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "age": {
          "type": "integer",
          "minimum": 0
        },
        "breed": {
          "type": "string"
        },
        "color": {
          "type": "string",
          "enum": [
            "black",
            "brown",
            "white",
            "golden"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "name",
        "age"
      ]
    },
    "Cat": {"type":  "object"}
  }
}

elephant.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Elephant",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minimum": 3,
      "maximum": 12
    },
    "age": {
      "type": "integer",
      "minimum": 0
    },
    "gender": {
      "type": "string",
      "enum": ["male", "female"]
    },
    "weight": {
      "description": "must be heavy..",
      "type": "number",
      "minimum": 0,
      "default": 30
    },
    "height": {
      "type": "number",
      "minimum": 0,
      "default": 100
    },
    "dogs": {
      "description": "Yes... every elephant needs a dog or two :-) ",
      "type": "array",
      "items": {
        "type": { "$ref": "schema/types.json#/definitions/Dog" }
      },
      "minimum": 1,
      "maximum": 2
    },
    "color": {
      "type": "string"
    }
  },
  "additionalProperties": false,
  "required": ["name", "age", "gender","height","dogs"]
}

generated code (elephant.d.ts)

/* eslint-disable */
/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */

export interface Elephant {
  name: string;
  age: number;
  gender: "male" | "female";
  /**
   * must be heavy..
   */
  weight?: number;
  height: number;
  /**
   * Yes... every elephant needs a dog or two :-)
   */
  dogs: {
    [k: string]: unknown;
  }[];
  color?: string;
}

generated code (types)

/* eslint-disable */
/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */

export interface Types {
  [k: string]: unknown;
}

cli

json2ts --unreachableDefinitions -i schema/ -o types/

Update

After changing the CLI to json2ts -i schema/ -o types/ --unreachableDefinitions. The types (Dog,Cat) are generated (see below) but the dogs array is not using the Dog definition as I am expecting.
I am expecting that the generated Elephant will import the Dog and use it in the array declaration.

types.d.ts (after adding the unreachableDefinitions cli flag)

/* eslint-disable */
/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */

export interface Types {
  [k: string]: unknown;
}
/**
 * This interface was referenced by `Types`'s JSON-Schema
 * via the `definition` "Dog".
 */
export interface Dog {
  name: string;
  age: number;
  breed?: string;
  color?: "black" | "brown" | "white" | "golden";
}
/**
 * This interface was referenced by `Types`'s JSON-Schema
 * via the `definition` "Cat".
 */
export interface Cat {
  breed?: string;
}

The below code is my expected output

How can I get there ?

/* eslint-disable */
/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */

import { Dog } from "./types";

 export interface Elephant {
  name: string;
  age: number;
  gender: "male" | "female";
  /**
   * must be heavy..
   */
  weight?: number;
  height: number;
  /**
   * Yes... every elephant needs a dog or two :-)
   */
  dogs: Dog[];
  color?: string;
}
GabenGar commented 9 months ago

"minimum" and "maximum" keywords are used for "number" types, "array" types use "minItems" and "maxItems" instead. Also you have to declare the types in "$defs" instead.