json-schema-to-typescript icon indicating copy to clipboard operation
json-schema-to-typescript copied to clipboard

Adding allOf generates intersection types

Open valcker opened this issue 5 years ago • 3 comments

I am using the following JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Demo",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "hostname": {
      "type": "string"
    },
    "enable_subconfig": {
      "type": "boolean"
    }
  },
  "required": ["enable_subconfig"],
  "allOf": [
    {
      "if": {
        "properties": {
          "enable_subconfig": {
            "enum": [true]
          }
        }
      },
      "then": {
        "required": ["hostname"]
      },
      "else": {}
    }
  ]
}

Which generates the following types:

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

export type Demo = Demo1 & Demo2;
export type Demo1 = {
  [k: string]: unknown;
};

export interface Demo2 {
  hostname?: string;
  enable_subconfig: boolean;
}

Although it normally should generate:

export interface Demo {
    enable_subconfig: boolean;
    hostname?:        string;
}

Removing the allOf fixes the problem. Is there anything I can do in order to fix this behaviour?

Thanks!

valcker avatar Feb 24 '21 16:02 valcker

I believe I just ran into the same problem with a definition like:

{
  "type": "object",
  "properties": {
    "minimum_instances": {
      "type": "integer",
      "minimum": 1,
      "allOf" :[
        { "maximum": 80 },
        { "maximum": { "$data": "1/maximum_instances" } }
      ]
    },
    "maximum_instances": {
      "type": "integer",
      "minimum": 1,
      "maximum": 80
    }
  }
}

Where the output type becomes:

export interface Example {
  minimum_instances?: {
    [k: string]: unknown;
  } & number;
  maximum_instances?: number;
}

Whereas I would expect:

export interface Example {
  minimum_instances?: number;
  maximum_instances?: number;
}

Nevon avatar Mar 01 '21 11:03 Nevon

Hey there! Does adding "additionalProperties": false to your allOf cases fix the issue for you? What output would you expect for the allOf -- nothing?

bcherny avatar Mar 28 '21 23:03 bcherny

Hey!

Modifying the schema to this (by adding the "additionalProperties": false to the allOf itself modifies the output.

Here is the updated schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Demo",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "hostname": {
      "type": "string"
    },
    "enable_subconfig": {
      "type": "boolean"
    }
  },
  "required": ["enable_subconfig"],
  "allOf": [
    {
      "additionalProperties": false,
      "if": {
        "properties": {
          "enable_subconfig": {
            "enum": [true]
          }
        }
      },
      "then": {
        "required": ["hostname"]
      },
      "else": {}
    }
  ]
}

Here is the output:

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

export type Demo = Demo1 & Demo2;
export type Demo1 = {};

export interface Demo2 {
  hostname?: string;
  enable_subconfig: boolean;
}

It's a bit better as we don't have the [k: string]: unknown; but we still have 2 interfaces Demo1 and Demo2. Not ideal, but I guess we can live with that.

valcker avatar Mar 30 '21 15:03 valcker