openapi-ts / openapi-typescript

Generate TypeScript types from OpenAPI 3 specs
https://openapi-ts.dev
MIT License
5.99k stars 474 forks source link

Schemas using $ref give different output to identical inlined spec when using defaults #1903

Open philios33 opened 2 months ago

philios33 commented 2 months ago

Description

Defining an object using an external file $ref gives different typing outputs for schemas with keys that have defaults defined. Object keys are incorrectly marked as required/non optional if they contain a default and are defined within an externally $ref ed file. The same schema generates correctly without using a $ref.

Name Version
openapi-typescript 7.4.0
Node.js 20.16.0
OS + version macOS 14.5

Reproduction

spec.json alpha.json

Gives the following typing on the /failing endpoint:

{
    /** @default false */
    bool_with_default: boolean;
    bool_with_no_default?: boolean;
    /** @default ok */
    string_with_default: string;
    string_with_no_default?: string;
};

Note, the omission of the ? optional identifier on keys that have defaults set.

Expected result

All fields should be marked as optional in both of the endpoints. Giving a field a default should not make it mandatory. Using an external file with $ref should be logically identical to an inline spec.

{
    /** @default false */
    bool_with_default?: boolean;
    bool_with_no_default?: boolean;
    /** @default ok */
    string_with_default?: string;
    string_with_no_default?: string;
}

Checklist

philios33 commented 2 months ago

Gah, I just found a similar closed ticket that references this merged PR https://github.com/openapi-ts/openapi-typescript/pull/1746

All problems go away when I use --default-non-nullable false which is weird. I don't even use nullable anywhere, plus the value for this param should default to false according to the latest docs.

philios33 commented 2 months ago

I've taken a look at the code, and basically the whole --default-non-nullable option now defaults to true (since v7), but the feature is essentially useless. It has some logic to attempt to disable it if you are within parameters, requestBody or requestBodies (inputs), but that does not work if you are using a schema $ref.

This feature seems to cater for people who are using defaults on their OUTPUT schemas to make fields mandatory in their output types. However, the default key is only ever used with api INPUTS to specify to the consumer what the value would be if you omit it.

Please can somebody explain the point of this feature (now enabled by default)?