fix(downgrader): stop emitting nullable without type in 3.1 to 3.0 - #20
Conversation
Null-only schemas and null consts were converted with nullable: true but
no type. OpenAPI 3.0 ignores nullable without type, and Ajv 8 refuses to
compile such schemas, which broke the common anyOf: [X, {type: 'null'}]
pattern. Emit a plain null enum instead.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Null-only schemas no longer emit
nullablewithouttype— therest.length === 0branch inapplyTypesdropsout.nullable = true, so{ type: 'null' }now converts to{ enum: [null] }instead of the Ajv-invalid{ enum: [null], nullable: true }. const: nullno longer forcesnullable—convertConstis reduced to emitting the single-valueenum, which also fixes{ const: null, type: 'string' }: it previously acceptednulland now correctly accepts nothing.- Tests and README — updated the null-only and
const: nullexpectations, added theanyOf: [X, { type: 'null' }]FastAPI pattern, the multi-type null const, and the contradicting-type cases; synced the mapping table.
I independently reproduced the Ajv 8.20.0 behaviour against the pnpm-store copy: { nullable: true } fails to compile with "nullable" cannot be used without "type", while { enum: [null] }, { type: 'string', enum: [null] }, and anyOf: [{ type: 'string' }, { enum: [null] }] all compile and accept exactly the values the 3.1 sources do. pnpm test (353 passing), pnpm lint, and pnpm type:check are all green.
One non-blocking note: the repo has no Ajv dependency, so the semantic-equivalence checks described in the PR body are not captured by the in-repo suite (@seriousme/openapi-schema-validator only validates structure). The specific regression is still pinned by the toEqual expectations, so nothing needs to change here.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

The 3.1 → 3.0 downgrader no longer puts
nullable: trueon schemas that have notype. Null-only schemas now come out as{ enum: [null] }. As a result, the Pydantic/FastAPI patternanyOf: [X, { type: 'null' }]produces schemas that Ajv 8 can compile.Fixes
type: 'null'andconst: nullno longer producenullablewithouttype. OpenAPI 3.0 ignores that combination, and Ajv 8 refuses to compile it ("nullable" cannot be used without "type").const: nullalongside several types no longer addsnullableat the top level, where there is notype, so these schemas compile too.{ const: null, type: 'string' }now accepts no value, like the source schema. Before, it acceptednull.Schemas whose
typelistsnullalongside another type are unchanged: they still gettypeplusnullable: true.Testing
const: nullexpectations, and added cases for theanyOfpattern, a multi-type null const, and a null const with a non-null type.