Skip to content

[BUG][typescript-fetch] Crash on required nullable datetime #21820

@kradical

Description

@kradical
Description

7.15 Generates code that crashes at runtime for a required nullable datetime (and probably date too).

see: 65c3126

openapi-generator version

7.15, regression from 7.11 for sure, likely introduced when the linked commit went out in 7.14

OpenAPI declaration file content or url
{
  "type": "object",
  "properties": {
    "startedAt": {
      "type": "string",
      "format": "date-time",
      "nullable": true
    }
  },
  "required": [
    "startedAt"
  ]
}
Generation Details

generated with a command like:

java -jar bin/openapi-generator-cli-7.15.0.jar generate -i path/to/schema.json -g typescript-fetch -o path/to/apiGen -c bin/typescript.json

Generates code like:

'startedAt': ((value['startedAt'] as any).toISOString()),

which will crash when value['startedAt'] is null

Related issues/PRs

65c3126
#21133
#21132
#11307

Suggest a fix

{{#isDateType}}
'{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}']{{#isNullable}} as any{{/isNullable}}).toISOString().substring(0,10)),
{{/isDateType}}
{{#isDateTimeType}}
'{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}']{{#isNullable}} as any{{/isNullable}}).toISOString()),
{{/isDateTimeType}}

{{#isDateType}}
'{{baseName}}': {{^required}}value['{{name}}'] == null ? value['{{name}}'] : {{/required}}{{#isNullable}}{{#required}}value['{{name}}'] == null ? value['{{name}}'] : {{/required}}{{/isNullable}}value['{{name}}'].toISOString().substring(0,10),
{{/isDateType}}

{{#isDateTimeType}}
'{{baseName}}': {{^required}}value['{{name}}'] == null ? value['{{name}}'] : {{/required}}{{#isNullable}}{{#required}}value['{{name}}'] == null ? value['{{name}}'] : {{/required}}{{/isNullable}}value['{{name}}'].toISOString(),
{{/isDateTimeType}}

The theory is if something is not required AND nullable we kind of want to give the consumer freedom to pass in undefined OR null have have that value carry onto the server. Sometimes servers treat undefined or missing differently than null (for better or worse) so allowing either or is pretty important IMO. Otherwise if something is just not required its caught by the first block, and finally if something is nullable AND required then it is caught by the second block. you may notice the code is repeated, if mustache had an OR operator we could just do it in one block "if not required OR nullable -> do thing".

We don't need to cast it to any, typescript takes care of that via == null and type narrowing on the second branch of the conditional.

PR here: #21821

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions