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

[openapi-typescript] Incorrect type generated for nullable objects

Open JohanAlteruna opened this issue 1 year ago • 2 comments

Thanks everyone for the new updates of openapi-typescript! I have found an issue which I believe might be related to the new major version (7).

Description

In version 7.3.0 and OpenAPI version 3.0.3, combining type: object and nullable: true does not produce the expected union type.

Reproduction

Run the CLI with default options on the following schema:

openapi: "3.0.3"
info: { title: "Test", version: "0" }
servers:
  - url: "example.com"
components:
  schemas:
    obj1:
      type: object
      nullable: true
paths: {}

Expected result

schemas: {
  obj1: Record<string, never> | null;
};

Actual Result

schemas: {
  obj1: Record<string, never>;
};

Checklist

The example given above works fine with type: string and nullable: true. It also works in openapi-typescript version 6.7.6.

JohanAlteruna avatar Aug 05 '24 14:08 JohanAlteruna

As a side note, I also think that Record<string, never> should be replaced with a more inclusive type for arbitrary objects. For example, there are use cases in which API consumers and/or implementations are allowed to send objects with arbitrary properties (and arbitrary properties are allowed by default in JSON schema AFAIK). In such cases, Record<string, never> will prevent all legal values except for the empty object ({}). I would suggest that the type Record<string, unknown> is used instead.

JohanAlteruna avatar Aug 05 '24 14:08 JohanAlteruna

You’re right I don’t think we’re testing for this. This should be an easy fix and we’d welcome a PR on it from anyone 🙂

As a side note, I also think that Record<string, never> should be replaced with a more inclusive type for arbitrary objects.

We’ve had this suggestion before. But this library’s whole purpose is to help you catch where your runtime code deviates from your declared schema. As documented, if you declare an empty object in your schema, TS is going to flag this for you as a potential bug. Perhaps you’re autogenerating these schemas and there was a bug! It’s being overly strict for your benefit, to alert you of where your schema is incomplete, which is also at the boundary of where TS can’t typecheck for you anymore. Appreciate the suggestion, and we’ll always look for newer and better ways to do things. But in situations like this, we’ll always err on the side of being too strict rather than too loose.

drwpow avatar Aug 14 '24 09:08 drwpow

I found a similar issue: the nullable is not taken into account on a type: object using a ref (even if the object has properties and even when using the new syntax type: [object, "null"]).

Reproduction

openapi: "3.0.3"
info: { title: "Test", version: "0" }
servers:
  - url: "example.com"
components:
  schemas:
    obj1Ref:
      properties:
        id:
          type: string
    obj1:
      type: object
      nullable: true
      $ref: '#/components/schemas/obj1Ref'
paths: {}

Expected result

obj1: components["schemas"]["obj1Ref"] | null;

Actual Result

obj1: components["schemas"]["obj1Ref"];

Maybe I, or one of my colleagues, can try to open a PR for both cases