openapi-ts / openapi-typescript

Generate TypeScript types from OpenAPI 3 specs

Home Page:https://openapi-ts.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"AdditionalProperties" reflects onto existing properties and causes TypeScript compile errors

grepfruit19 opened this issue · comments

Description

When provided a schema that has additional properties, the generated TypeScript generates a "catch-all" key-value pair that causes compile errors.

Name Version
openapi-typescript 6.7.5
Node.js 20.11.0
OS + version macOS 14

Reproduction

Here is the JSON I'm converting

{
  "openapi": "3.0.1",
  "info": { "title": "TESTFILE", "version": "1.0.0" },
  "security": [{ "Authorization": [] }],
  "components": {
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "detailMessageArguments": {
            "type": "array",
            "items": { "type": "object" }
          },
          "detailMessageCode": { "type": "string" },
          "titleMessageCode": { "type": "string" },
          "headers": {
            "type": "object",
            "properties": {
              "accessControlAllowHeaders": {
                "type": "array",
                "items": { "type": "string" }
              },
              "accessControlAllowOrigin": { "type": "string" },
              "accessControlExposeHeaders": {
                "type": "array",
                "items": { "type": "string" }
              },
              "accessControlAllowCredentials": { "type": "boolean" },
              "accessControlMaxAge": { "type": "integer", "format": "int64" },
              "accessControlRequestHeaders": {
                "type": "array",
                "items": { "type": "string" }
              },
              "basicAuth": { "type": "string", "writeOnly": true },
              "ifUnmodifiedSince": { "type": "integer", "format": "int64" },
              "acceptCharset": {
                "type": "array",
                "items": { "type": "string" }
              },
              "all": {
                "type": "object",
                "additionalProperties": { "type": "string" },
                "writeOnly": true
              },
              "lastModified": { "type": "integer", "format": "int64" },
              "date": { "type": "integer", "format": "int64" },
              "contentLength": { "type": "integer", "format": "int64" },
              "ifModifiedSince": { "type": "integer", "format": "int64" }
            },
            "additionalProperties": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        }
      }
    }
  }
}

And here is the outputted TypeScript code:

export interface components {
  schemas: {
    ErrorResponse: {
      detailMessageArguments?: Record<string, never>[];
      detailMessageCode?: string;
      titleMessageCode?: string;
      headers?: {
        accessControlAllowHeaders?: string[];
        accessControlAllowOrigin?: string;
        accessControlExposeHeaders?: string[];
        accessControlAllowCredentials?: boolean;
        /** Format: int64 */
        accessControlMaxAge?: number;
        accessControlRequestHeaders?: string[];
        basicAuth?: string;
        /** Format: int64 */
        ifUnmodifiedSince?: number;
        acceptCharset?: string[];
        all?: {
          [key: string]: string;
        };
        /** Format: int64 */
        lastModified?: number;
        /** Format: int64 */
        date?: number;
        /** Format: int64 */
        contentLength?: number;
        /** Format: int64 */
        ifModifiedSince?: number;
        [key: string]: string[] | undefined; // <------------ This is the line that's causing issues
      };
    };
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

If you attempt to parse this in TypeScript, it will give you errors such as

Property 'ifModifiedSince' of type 'number | undefined' is not assignable to 'string' index type 'string[] | undefined'.ts(2411)

This is occurring because additionalProperties is telling the object that all of its values should be string[], as opposed to just unlisted values.

Expected result

I don't know what the expected result should be honestly, but this doesn't compile so certainly not this. I'm not sure if this is a limitation of TypeScript as a language, if it is, maybe just generate something like [key: string]: unknown?

Checklist

This is a known issue and 7.x will NOT have | undefined for this very reason. It originally meant to improve type safety and discourage use of additionalProperties, but has caused issues in 6.x. Changing this would be a breaking change for many people, so it’s saved for the next major release.

This is already largely captured in #1055 (and other discussions); feel free to add to additional issues with more info if you’d like.