openapi-typescript-codegen icon indicating copy to clipboard operation
openapi-typescript-codegen copied to clipboard

Add support for `const` keyword

Open robertadkins opened this issue 1 year ago • 8 comments

I have a usecase where it would be helpful to support constant values via the const keyword.

Say we have an api spec containing some models like:

{
  "components": {
    "schemas": {
      "Animal": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/Dog"
          },
          {
            "$ref": "#/components/schemas/Cat"
          }
        ]
      },
      "Dog": {
        "type": "object",
        "properties": {
          "type": {
            "const": "Dog"
          },
          "isPuppy": {
            "type": "boolean",
          }
        }
      },
      "Cat": {
        "properties": {
          "type": {
            "const": "Cat"
          },
          "isKitten": {
            "type": "boolean",
          }
        }
      }
    }
  }
}

In typescript, this should map to something like:

type Animal = Dog | Cat;
type Dog = {
  type: "Dog";
  isPuppy: boolean;
};
type Cat = {
  type: "Cat";
  isKitten: boolean;
};

This way, we can narrow the type in a useful way:

function isBaby(animal: Animal): boolean {
  switch(animal.type) {
    case "Dog":
      return animal.isPuppy;
    case "Cat":
      return animal.isKitten;
  }
}

However, openapi-typescript-codegen maps const values to any types, so the type information is lost.

robertadkins avatar Oct 14 '23 00:10 robertadkins

I don't see a spec including

"type": {
  "const": "Cat"
},

being compatible with the OpenAPI spec, where type is required to be a string. It would be weird to deviate the codegen to something that is not following the specification it is supposed to generate from, or am i missing something?

mbergen avatar Oct 18 '23 07:10 mbergen

type is required to be a string.

Ah, sorry I've actually overloaded type here. In

"type": {
    "const": "Cat"
},

type is the name of a property on the Cat object. For clarity, we could give the property a different name, like id:

"id": {
    "const": "Cat"
},

The issue still applies here independent of the property name.

robertadkins avatar Oct 18 '23 17:10 robertadkins

That would still be an extension to the OpenAPI spec, or am i misunderstanding your proposal? As an alternative, did you try to use an enum with the possible values your subclasses can have as a type to handle this?

mbergen avatar Oct 19 '23 06:10 mbergen

The OpenAPI spec includes the const keyword as of version 3.1 and was explicitly addressed as part of https://github.com/OAI/OpenAPI-Specification/pull/1977. From the spec:

The Schema Object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. This object is a superset of the JSON Schema Specification Draft 2020-12.

For more information about the properties, see JSON Schema Core and JSON Schema Validation.

The JSON Schema Validation spec above defines the const keyword (alongside with enum and type as generic validation keywords).

Some other libraries already have support for const, e.g. openapi-typescript added support in https://github.com/drwpow/openapi-typescript/pull/831.

robertadkins avatar Oct 19 '23 15:10 robertadkins

I see, i just looked at the currently supported v3.0, not at v3.1, sorry.

mbergen avatar Oct 19 '23 18:10 mbergen

Ah, I see! So only v3.0 is currently supported here. Any opposition to starting v3.1 support with this change? Adding const should be a non-breaking update to v3.0 parsing.

robertadkins avatar Oct 19 '23 18:10 robertadkins

I'm by no means opposed, but i'm also not the maintainer of this library.

mbergen avatar Oct 23 '23 08:10 mbergen

This would be great, in fact this is making this generator not usable with the SpatioTemporal Asset Catalogs standard, which uses a stac_version constant

keul avatar Nov 16 '23 16:11 keul