Skip to content

Integration: support z.looseRecord() and z.exactOptional()#3157

Merged
RobinTail merged 11 commits into
masterfrom
feat-zts-upd-2025-12-31
Jan 1, 2026
Merged

Integration: support z.looseRecord() and z.exactOptional()#3157
RobinTail merged 11 commits into
masterfrom
feat-zts-upd-2025-12-31

Conversation

@RobinTail

@RobinTail RobinTail commented Dec 31, 2025

Copy link
Copy Markdown
Owner

Supporting the latest features of Zod 4.2 and 4.3 by the Integration generator

Summary by CodeRabbit

  • New Features
    • Added a "loose" mode for Record types to allow more flexible key typing.
    • Improved handling of optional vs. undefined for interface properties with a configurable option and broader support for optional-like wrapped types.
  • Tests
    • Expanded test coverage for additional Zod features (loose records, exact-optional behavior, composite schemas).
  • Chores
    • Updated changelog with the new integration details (v26.3.0).

✏️ Tip: You can customize this high-level summary in your review settings.

@RobinTail RobinTail added the enhancement New feature or request label Dec 31, 2025
@coderabbitai

coderabbitai Bot commented Dec 31, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a hasUndefined option to TypeScript property generation, separates optional/undefined computation in schema generation, adds support for loose Record schemas, extends wrapped-type handling to include exact-optional variants, and updates tests and changelog.

Changes

Cohort / File(s) Summary
TypeScript API parameter enhancement
express-zod-api/src/typescript-api.ts
makeInterfaceProp signature now accepts hasUndefined?: boolean (defaults to isOptional). Property signature construction uses hasUndefined to decide whether to union the type with undefined.
Schema generation handlers
express-zod-api/src/zts.ts
onObject computes and forwards both isOptional and hasUndefined to makeInterfaceProp. onRecord supports def.mode === "loose" by returning an intersection with a looser key type. onWrapped includes z.core.$ZodExactOptional among optional-like wrappers.
Tests
express-zod-api/tests/zts.spec.ts
Adds test cases exercising looseRecord, exactOptional(), and additional example fields (codec/slug/hex/hash/xor) to cover the new/changed Zod features.
Changelog
CHANGELOG.md
Adds v26.3.0 entry documenting support for z.looseRecord() and handling of exact-optional/exactOptional variants.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

refactoring

Poem

🐇 I nibbled types and found a clue,
hasUndefined now hops into view.
Loose records scamper, exacts tuck in tight,
Tests clap their paws in the moonlight. 🥕

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main changes: adding support for two specific Zod features (z.looseRecord() and z.exactOptional()) in the Integration generator, matching the primary content of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ce8eee and 9a22b97.

📒 Files selected for processing (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build (22.12.0)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread express-zod-api/tests/__snapshots__/zts.spec.ts.snap Outdated
Comment thread express-zod-api/tests/__snapshots__/zts.spec.ts.snap Outdated
@coveralls-official

coveralls-official Bot commented Dec 31, 2025

Copy link
Copy Markdown

Coverage Status

coverage: 100.0%. remained the same
when pulling 9a22b97 on feat-zts-upd-2025-12-31
into 486fd36 on master.

@RobinTail RobinTail marked this pull request as ready for review January 1, 2026 09:06
@RobinTail RobinTail changed the title ZTS update Integration: support z.looseRecord() and z.exactOptional() Jan 1, 2026
@RobinTail RobinTail force-pushed the feat-zts-upd-2025-12-31 branch from 4619574 to 1ce8eee Compare January 1, 2026 12:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.md (1)

5-9: Improve phrasing in the changelog entry.

The phrase "Object properties made by" on line 9 is slightly awkward. Consider "Object properties created by" for consistency and clarity (which aligns with the phrasing used elsewhere in the codebase and PR context).

Current:

- Object properties made by `z.exactOptional()` or `ZodType::exactOptional()` method.

Suggested:

- Object properties created by `z.exactOptional()` or `ZodType::exactOptional()` method.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b891d2 and 1ce8eee.

📒 Files selected for processing (1)
  • CHANGELOG.md
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/tests/form-schema.spec.ts:31-31
Timestamp: 2025-05-27T19:27:13.492Z
Learning: Zod version 3.25.0 and later expose the Zod v4 API through the special import paths "zod/v4" and "zod/v4/core", allowing v4 features like .loose() to be used even when the package.json dependency shows a 3.x version.
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2697
File: CHANGELOG.md:5-5
Timestamp: 2025-06-02T21:11:20.768Z
Learning: In the express-zod-api repository, RobinTail follows a release workflow where package.json version is only updated on the master branch after merging all planned release changes. Changelog entries may show future version numbers while package.json remains at the previous version during feature development, and this is intentional workflow, not a version inconsistency that needs to be flagged.
📚 Learning: 2025-05-27T19:27:13.492Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/tests/form-schema.spec.ts:31-31
Timestamp: 2025-05-27T19:27:13.492Z
Learning: Zod version 3.25.0 and later expose the Zod v4 API through the special import paths "zod/v4" and "zod/v4/core", allowing v4 features like .loose() to be used even when the package.json dependency shows a 3.x version.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-05-27T20:08:50.699Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/src/metadata.ts:5-13
Timestamp: 2025-05-27T20:08:50.699Z
Learning: The `_zod` property in Zod v4 schemas is officially documented and recommended for library authors to differentiate between Zod 3 and Zod 4 schemas at runtime, despite the underscore prefix. This is explicitly mentioned in Zod's library authors documentation and is not a private internal property.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-08-05T14:43:24.702Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2869
File: zod-plugin/package.json:42-44
Timestamp: 2025-08-05T14:43:24.702Z
Learning: Zod version 4 has been officially released and is stable. As of August 2025, the latest published version is 4.0.14 (published July 30, 2025). Zod v4 is available on npm and can be used in peer dependencies with version constraints like "^4.0.0".

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-05-27T20:27:17.015Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 2546
File: express-zod-api/src/json-schema-helpers.ts:1-3
Timestamp: 2025-05-27T20:27:17.015Z
Learning: The JSONSchema type is not exported from the main "zod" module and must be imported from "zod/v4/core" when using Zod v4. This is acceptable for type-only imports as they don't create runtime dependencies.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-08-01T09:48:13.742Z
Learnt from: RobinTail
Repo: RobinTail/express-zod-api PR: 0
File: :0-0
Timestamp: 2025-08-01T09:48:13.742Z
Learning: In express-zod-api, when migrating from Zod v3 to v4, the correct approach for internal type imports is to change from `import type { $ZodType } from "zod/v4/core"` to `import { z } from "zod"` and then use `z.core.$ZodType`. The zod/v4/core module is reexported as z.core by the main zod package, making this a valid and working approach.

Applied to files:

  • CHANGELOG.md

@RobinTail RobinTail force-pushed the feat-zts-upd-2025-12-31 branch from 1ce8eee to 9a22b97 Compare January 1, 2026 13:15

@RobinTail RobinTail left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🏁

@RobinTail RobinTail merged commit 921e9f0 into master Jan 1, 2026
13 checks passed
@RobinTail RobinTail deleted the feat-zts-upd-2025-12-31 branch January 1, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant