Skip to content

Conversation

@bankyadam
Copy link

@bankyadam bankyadam commented Dec 10, 2025

Summary

Fixes #533 - Resolves incorrect null handling for nullable parent objects containing nullable child properties.

Problem

When a schema defined a nullable object (type: object, nullable: true) with child properties that were also nullable, the generator was incorrectly adding an additional | null to the parent type. This happened because isNullMissingInType was detecting the | null from nested properties and incorrectly concluding that the parent type needed null added.

Example Issue

Given this schema:

{
  "type": "object",
  "nullable": true,
  "properties": {
    "email": { "type": "string", "nullable": true }
  }
}

Before: Generated redundant | null even though the parent was already properly nullable
After: Correctly generates { email?: string | null } | null

Solution

Refactored the isNullMissingInType method in src/schema-parser/schema-utils.ts to distinguish between:

  • Root-level nullable types (union with null at the top level)
  • Types with nested nullable properties (objects containing prop: string | null)

The fix uses regex patterns to detect only root-level null unions:

  • Pattern ending with | null
  • Pattern starting with null |
  • Exact match of null

This prevents false positives from nested nullable properties while correctly identifying when the parent type actually needs | null added.

Changes

Core Fix

  • src/schema-parser/schema-utils.ts: Improved isNullMissingInType logic with regex-based root-level null detection

Build Configuration

  • package.json: Changed ESM output extensions from .js to .mjs for better module resolution

Test Coverage

  • Added new test suite: tests/spec/nullable-parent-with-nullable-children/
  • Tests cover nullable parent objects with nullable child properties, nested nullable objects, and complex scenarios
  • Updated snapshots across multiple test suites to reflect correct nullable handling

Testing

All existing tests pass with updated snapshots showing correct nullable type generation. New test suite specifically validates the fix for nested nullable scenarios.


Note

Fixes null handling by only adding | null at the root type level, adds targeted tests, and updates snapshots accordingly.

  • Core Fix
    • Refactor src/schema-parser/schema-utils.ts:isNullMissingInType to detect only root-level null in unions (regex-based), avoiding false positives from nested nullable properties.
    • safeAddNullToType now leverages the corrected check to prevent duplicate | null on parent object types.
  • Tests
    • Add tests/spec/nullable-parent-with-nullable-children/ suite with schema and snapshot validating nullable parent + nullable children behavior.
    • Update snapshots (tests/__snapshots__/extended.test.ts.snap, tests/__snapshots__/simple.test.ts.snap, tests/spec/additional-properties-2.0/__snapshots__/basic.test.ts.snap) to reflect corrected nullability (e.g., unions with null, nullable record values).
  • Meta
    • Add changeset .changeset/giant-hats-work.md (patch).

Written by Cursor Bugbot for commit 6db9615. This will update automatically on new commits. Configure here.

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

🦋 Changeset detected

Latest commit: 6db9615

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
swagger-typescript-api Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@smorimoto
Copy link
Collaborator

smorimoto commented Dec 13, 2025

bugbot run

@acacode acacode deleted a comment from chatgpt-codex-connector bot Dec 13, 2025
const hasRootLevelNull =
type.trim() === nullKeyword ||
new RegExp(`\\|\\s*${nullKeyword}\\s*$`).test(type) || // Ends with | null
new RegExp(`^\\s*${nullKeyword}\\s*\\|`).test(type); // Starts with null |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Missing detection of null in middle of unions

The hasRootLevelNull check only detects null at the start or end of a union type string, but not when null appears in the middle (e.g., string | null | number). This can happen when a oneOf/anyOf schema has a { "type": "null" } child positioned between other schema children and the parent is also marked nullable: true. In such cases, isNullMissingInType would incorrectly return true, causing safeAddNullToType to add a redundant | null to the type. While TypeScript treats A | null | null equivalently to A | null, this produces unnecessarily verbose type output. The previous implementation using includes(" null") and includes("null ") would correctly detect null anywhere in the union.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nullable: true ignored if type: object and a property has nullable: true

3 participants