bcherny/json-schema-to-typescript

Property type changes from "unknown" to "{[k: string]: unknown}" when adding a description to the schema

Open

#432 opened on Jan 13, 2022

View on GitHub
 (2 comments) (2 reactions) (0 assignees)TypeScript (449 forks)github user discovery
bughelp wanted

Repository metrics

Stars
 (3,302 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

When generating typescript types for json-patch as defined at http://json.schemastore.org/json-patch, I found the output slightly suspicious, which I wanted to pick up here.

When I input the following string (where I just added a "type": "object" to the oneOf-items):

{
  "title": "JSON schema for JSONPatch files",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",

  "items": {
    "oneOf": [
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["value", "op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["add", "replace", "test"]
          },
          "value": {
            "description": "The value to add, replace or test."
          }
        }
      },
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["remove"]
          }
        }
      },
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["from", "op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["move", "copy"]
          },
          "from": {
            "$ref": "#/definitions/path",
            "description": "A JSON Pointer path pointing to the location to move/copy from."
          }
        }
      }
    ]
  },
  "definitions": {
    "path": {
      "description": "A JSON Pointer path.",
      "type": "string"
    }
  }
}

I get the following result:

/* tslint: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.
 */

/**
 * A JSON Pointer path.
 */
export type Path = string;
export type JSONSchemaForJSONPatchFiles = (
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "add" | "replace" | "test";
      /**
       * The value to add, replace or test.
       */
      value: {
        [k: string]: unknown;
      };
    }
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "remove";
    }
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "move" | "copy";
      /**
       * A JSON Pointer path.
       */
      from: string;
    }
)[];

You may notice the property value of the first object - it is generated as if I had defined it as an object with arbitrary properties of unknown type. Now, when I remove the property description of its definition (the resulting definition is here):

{
  "title": "JSON schema for JSONPatch files",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "array",

  "items": {
    "oneOf": [
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["value", "op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["add", "replace", "test"]
          },
          "value": {}
        }
      },
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["remove"]
          }
        }
      },
      {
        "type": "object",
        "additionalProperties": false,
        "required": ["from", "op", "path"],
        "properties": {
          "path": { "$ref": "#/definitions/path" },
          "op": {
            "description": "The operation to perform.",
            "type": "string",
            "enum": ["move", "copy"]
          },
          "from": {
            "$ref": "#/definitions/path",
            "description": "A JSON Pointer path pointing to the location to move/copy from."
          }
        }
      }
    ]
  },
  "definitions": {
    "path": {
      "description": "A JSON Pointer path.",
      "type": "string"
    }
  }
}

... the result looks as I would've expected it:

/* tslint: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.
 */

/**
 * A JSON Pointer path.
 */
export type Path = string;
export type JSONSchemaForJSONPatchFiles = (
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "add" | "replace" | "test";
      value: unknown;
    }
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "remove";
    }
  | {
      path: Path;
      /**
       * The operation to perform.
       */
      op: "move" | "copy";
      /**
       * A JSON Pointer path.
       */
      from: string;
    }
)[];

Is this a bug? Looks like it to me, since the pre- or absense of a description on a property shouldn't change its type, as of my understanding. I would like to have the description in place while still keeping it as type unknown.

Contributor guide