Skip to content

test(examples): assert generated inferred types contain no unknown recursively - #395

Merged
benjamineckstein merged 1 commit into
mainfrom
test/deep-no-unknown-inferred-types
Jun 23, 2026
Merged

test(examples): assert generated inferred types contain no unknown recursively#395
benjamineckstein merged 1 commit into
mainfrom
test/deep-no-unknown-inferred-types

Conversation

@benjamineckstein

@benjamineckstein benjamineckstein commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

The prior schema-shape property test only checked generated SOURCE TEXT for the "unknown" substring. This can be bypassed by a z.infer collapse to unknown: the #383 shape where source text says z.ZodType with no literal "unknown" substring, but the inferred type resolves to unknown. This adds a TYPE-LEVEL recursive DeepHasUnknown<T> assertion over inferred types (model interfaces + z.infer), providing compile-time proof that INFERRED types contain no unknown in any named field recursively.

Changes

Testing

  • pnpm --filter @codewithagents/examples run typecheck passes locally
  • Detection empirically proven: deliberately-leaky field makes typecheck fail
  • pnpm fallow:audit exits 0 (fallow "unused file" warning is warn-level only, expected for type-only assertion)
  • No generated files changed
  • eslint config does not lint examples/ (expected)

Notes

  • This is a test: change. Release Please will NOT create a version bump.
  • The fallow "unused file" finding is warn-level and expected for a type-only assertion file. It does not gate the audit.
  • Typechecked by Showcase (Drift + Typecheck) and Typecheck Generated Output CI jobs.

Summary by CodeRabbit

  • Tests
    • Added TypeScript type validation tests to verify Zod-generated type inferences are accurate across various scenarios, including nullable fields and complex nested schemas. These tests help prevent type-related regressions.

…cursively

Adds a compile-time DeepHasUnknown<T> assertion over the inferred z.infer<>
types and model interfaces of committed generated output (canada_holidays
cycles for #383, resend nullable arrays/objects for #390 and the object-null
fix, plus a large example for breadth). The existing property test only checked
generated source text for the "unknown" substring, which a z.infer collapse to
unknown (the #383 shape) can bypass; this checks the inferred type itself,
recursively, and self-tests that the detector actually fires.

Claude-Session: https://claude.ai/code/session_01JdgDU9EqCzmdNFm3gb2gFj
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds examples/type-assertions.ts, a compile-time TypeScript harness that uses recursive conditional types (DeepHasUnknown, AssertNoUnknown) to assert that z.infer<> outputs for cyclic Canada holiday schemas, resend nullable schemas, and Spotify schemas contain no spurious unknown. Updates examples/tsconfig.json to include the new file.

Changes

Compile-time unknown leak assertion harness

Layer / File(s) Summary
Unknown detection types and tsconfig wiring
examples/type-assertions.ts, examples/tsconfig.json
File-level docs describe the passthrough handling approach. IsAny, IsUnknownExact, NamedKeys, DeepHasUnknown, and AssertNoUnknown implement recursive unknown leak detection that ignores wide index signatures. tsconfig.json extends include to cover type-assertions.ts.
Regression assertions for cyclic, resend, and Spotify schemas
examples/type-assertions.ts
AssertNoUnknown is applied to HolidaySchema/ProvinceSchema via Pick<> and top-level unknown checks (#383), to RootSchema/ErrorSchema, to resend models (Email, Attachment, Domain, DomainRecord) for nullable array/object-null regressions (#390), and to Spotify types (ArtistObject, TrackObject, AudioFeaturesObject).
Non-vacuous self-tests
examples/type-assertions.ts
@ts-expect-error directives require compile failures for unknown leaked in arrays, union members, and whole-type positions, while requiring compile success for a passthrough-like intersection type where the wide index signature is excluded.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • codewithagents/openapi-zod-ts#385: Directly related — fixes the cyclic/self-referential schema generator behavior (#383) that the new HolidaySchema/ProvinceSchema assertions in this PR validate.
  • codewithagents/openapi-zod-ts#393: Directly related — fixes the nullable object/unknown-fallback regression (#390) in OpenAPI→Zod type generation that the resend AssertNoUnknown checks in this PR cover.

Poem

🐇 Hoppity-hop through inferred types I go,
Sniffing for unknown that shouldn't be so!
With DeepHasUnknown I dig through each layer,
And @ts-expect-error keeps the detector fair.
No unknown leaks shall slip past my ear—
The types are concrete, the compile is clear! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding a compile-time type assertion mechanism to ensure generated inferred types contain no unknown values recursively. This directly corresponds to the primary addition of type-assertions.ts and the tsconfig.json update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/deep-no-unknown-inferred-types

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


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

@github-actions

Copy link
Copy Markdown
Contributor

Fallow audit report

Found 3 findings.

Dead code (1)
Severity Rule Location Description
minor fallow/unused-file examples/type-assertions.ts:1 File is not reachable from any entry point
Dependencies (2)
Severity Rule Location Description
minor fallow/unused-dev-dependency examples/package.json:15 Package '@tanstack/react-query' is in devDependencies but never imported; imported in other workspaces: packages/integration, packages/petstore-fastify
minor fallow/unused-dev-dependency examples/package.json:17 Package 'react' is in devDependencies but never imported; imported in other workspaces: packages/integration, packages/petstore-fastify

Generated by fallow.

@github-actions github-actions 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.

Fallow audit report

1 inline finding selected for GitHub review.

@@ -0,0 +1,183 @@
// Compile-time assertions: generated inferred types must contain no unknown in named fields.

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.

warn fallow/unused-file: File is not reachable from any entry point

Run fallow fix --files or delete this file.

@benjamineckstein
benjamineckstein merged commit 44c7c83 into main Jun 23, 2026
17 of 18 checks passed
@benjamineckstein
benjamineckstein deleted the test/deep-no-unknown-inferred-types branch June 23, 2026 17:18
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.

1 participant