Bug Report Checklist
Description
When a property is nullable using an OpenAPI 3.1 type array ("type": ["null", "object"]) and its additionalProperties is a $ref, the generated model references the $ref'd type but never imports it, so the output does not compile.
Instead of importing the referenced model, the generator emits an import for a Null model that it never writes:
// @ts-ignore
import type { Null } from './null'; // <- ./null is never generated
export interface ParentNullableMap {
'map'?: { [key: string]: Child; }; // <- Child referenced, never imported
}
tsc then fails with:
models/parent-nullable-map.ts(21,30): error TS2304: Cannot find name 'Child'.
Two things narrow it down:
- The nullable type array is what triggers it. With
"type": "object" instead of "type": ["null", "object"], the same property imports Child correctly.
additionalProperties is specific. A nullable array of the same $ref ("type": ["null", "array"] with items: {$ref}) is generated correctly, in the same run — included below as a control.
The nullable is also silently dropped on the affected property: 'map'?: { [key: string]: Child; } has no | null, while the control correctly produces 'list'?: Array<Child> | null.
Reproduces with withSeparateModelsAndApi=true.
openapi-generator version
7.24.0 (via the openapitools/openapi-generator-cli:v7.24.0 Docker image). Not tested against earlier versions.
OpenAPI declaration file content or url
{
"openapi": "3.1.0",
"info": {"title": "repro", "version": "1.0.0"},
"paths": {},
"components": {
"schemas": {
"Child": {"type": "object", "properties": {"name": {"type": "string"}}},
"ParentNullableMap": {
"type": "object",
"properties": {
"map": {"type": ["null", "object"], "additionalProperties": {"$ref": "#/components/schemas/Child"}}
}
},
"ParentNullableArray": {
"type": "object",
"properties": {
"list": {"type": ["null", "array"], "items": {"$ref": "#/components/schemas/Child"}}
}
}
}
}
}
validate reports no errors on this spec (only "unused model" recommendations, since paths is empty).
Command line used for generation
docker run --rm -v "$PWD:/local" openapitools/openapi-generator-cli:v7.24.0 \
generate -i /local/minimal.json -g typescript-axios -o /local/out \
--additional-properties=withSeparateModelsAndApi=true,modelPackage=models,apiPackage=api
Steps to reproduce
- Save the spec above as
minimal.json.
- Run the command above.
models/parent-nullable-map.ts imports Null from ./null and references Child with no import for it. models/null.ts does not exist.
models/parent-nullable-array.ts — the control — imports Child correctly.
- Type-check the output, e.g.
tsc --noEmit --strict --skipLibCheck --target es2020 --module esnext --moduleResolution bundler models/*.ts, and it fails with TS2304: Cannot find name 'Child'.
Actual output
// models/parent-nullable-map.ts (BROKEN)
// @ts-ignore
import type { Null } from './null';
export interface ParentNullableMap {
'map'?: { [key: string]: Child; };
}
// models/parent-nullable-array.ts (control, correct)
// @ts-ignore
import type { Child } from './child';
export interface ParentNullableArray {
'list'?: Array<Child> | null;
}
Expected output
// models/parent-nullable-map.ts
import type { Child } from './child';
export interface ParentNullableMap {
'map'?: { [key: string]: Child; } | null;
}
Related issues/PRs
Suggest a fix
The nullable type array appears to be consumed before the $ref inside additionalProperties is registered as an import, and a Null model is substituted in its place. Two observations that may help locate it:
- The
Null import is emitted for the nullable-type-array case generally, not only when a bare {"type": "null"} schema exists — the spec above contains no such schema, yet the import appears.
- The
// @ts-ignore above generated imports masks the dangling ./null import, so the failure surfaces at the usage site rather than the import, which makes it harder to trace. In the array (control) path the same @ts-ignore line is present but the import is correct.
A workaround for anyone hitting this: pre-process the spec to drop "null" from the type array on properties whose additionalProperties is a $ref (accepting the loss of nullability on those properties), which restores a compiling client.
Bug Report Checklist
Description
When a property is nullable using an OpenAPI 3.1 type array (
"type": ["null", "object"]) and itsadditionalPropertiesis a$ref, the generated model references the$ref'd type but never imports it, so the output does not compile.Instead of importing the referenced model, the generator emits an import for a
Nullmodel that it never writes:tscthen fails with:Two things narrow it down:
"type": "object"instead of"type": ["null", "object"], the same property importsChildcorrectly.additionalPropertiesis specific. A nullable array of the same$ref("type": ["null", "array"]withitems: {$ref}) is generated correctly, in the same run — included below as a control.The nullable is also silently dropped on the affected property:
'map'?: { [key: string]: Child; }has no| null, while the control correctly produces'list'?: Array<Child> | null.Reproduces with
withSeparateModelsAndApi=true.openapi-generator version
7.24.0 (via the
openapitools/openapi-generator-cli:v7.24.0Docker image). Not tested against earlier versions.OpenAPI declaration file content or url
{ "openapi": "3.1.0", "info": {"title": "repro", "version": "1.0.0"}, "paths": {}, "components": { "schemas": { "Child": {"type": "object", "properties": {"name": {"type": "string"}}}, "ParentNullableMap": { "type": "object", "properties": { "map": {"type": ["null", "object"], "additionalProperties": {"$ref": "#/components/schemas/Child"}} } }, "ParentNullableArray": { "type": "object", "properties": { "list": {"type": ["null", "array"], "items": {"$ref": "#/components/schemas/Child"}} } } } } }validatereports no errors on this spec (only "unused model" recommendations, sincepathsis empty).Command line used for generation
Steps to reproduce
minimal.json.models/parent-nullable-map.tsimportsNullfrom./nulland referencesChildwith no import for it.models/null.tsdoes not exist.models/parent-nullable-array.ts— the control — importsChildcorrectly.tsc --noEmit --strict --skipLibCheck --target es2020 --module esnext --moduleResolution bundler models/*.ts, and it fails withTS2304: Cannot find name 'Child'.Actual output
Expected output
Related issues/PRs
typescript-axioswithwithSeparateModelsAndApi, but a different trigger:additionalPropertiesof type array with a$ref, on OpenAPI 3.0. That report notes the plainadditionalProperties: {$ref}case works, which matches what I see — it only breaks here once the 3.1 nullable type array is added.Suggest a fix
The nullable type array appears to be consumed before the
$refinsideadditionalPropertiesis registered as an import, and aNullmodel is substituted in its place. Two observations that may help locate it:Nullimport is emitted for the nullable-type-array case generally, not only when a bare{"type": "null"}schema exists — the spec above contains no such schema, yet the import appears.// @ts-ignoreabove generated imports masks the dangling./nullimport, so the failure surfaces at the usage site rather than the import, which makes it harder to trace. In the array (control) path the same@ts-ignoreline is present but the import is correct.A workaround for anyone hitting this: pre-process the spec to drop
"null"from the type array on properties whoseadditionalPropertiesis a$ref(accepting the loss of nullability on those properties), which restores a compiling client.