Skip to content

Add t.Union/t.Intersection handling in property enumerations/checks#1719

Merged
SaltyAom merged 6 commits intoelysiajs:mainfrom
coreh:union-intersection-handling
Feb 9, 2026
Merged

Add t.Union/t.Intersection handling in property enumerations/checks#1719
SaltyAom merged 6 commits intoelysiajs:mainfrom
coreh:union-intersection-handling

Conversation

@coreh
Copy link
Copy Markdown
Contributor

@coreh coreh commented Feb 2, 2026

Hit this error:

TypeError: undefined is not an object (evaluating 'Object.keys(properties)')
    at keys (unknown)\n    at <anonymous> (/app/node_modules/elysia/src/dynamic-handle.ts:416:36)
    at processTicksAndRejections (native:7:39)

Looking into it, realized elysia is doing naive .properties-based checks and iteration in a couple of places, which meant that routes using t.Union/t.Intersect would either crash (my case) or silently behave incorrectly.

Also the files code was handling .anyOf but not .allOf or .oneOf.

Summary by CodeRabbit

  • Bug Fixes

    • Safer, more robust handling of composite schemas (unions/intersections) across query, body, cookie and file validation.
    • Prevented crashes and improved default/value detection when schema properties are absent or nested.
    • Improved reliability of file upload handling in complex schema compositions.
  • Tests

    • Added extensive tests for unions, intersections, file uploads, and query coercion/array scenarios.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 2, 2026

Walkthrough

Introduces getSchemaProperties(schema) and refactors modules to use it instead of direct schema.properties access, updating schema traversal across unions/intersects, adjusting related getters, and adding tests for composite-schema property handling, file uploads, and query validation in union contexts.

Changes

Cohort / File(s) Summary
Schema utilities
src/schema.ts
Add getSchemaProperties(schema) to aggregate object properties across composite schemas (allOf/anyOf/oneOf). hasProperty() now always returns boolean and traverses composite schemas; minor getter non-null assertion changes.
Compose logic
src/compose.ts
Replace direct schema.properties accesses with getSchemaProperties() for query, candidate (union/intersect) and body validation flows; import updated.
Dynamic handler
src/dynamic-handle.ts
Use getSchemaProperties() when injecting defaults and iterating cookie/validator/body properties; add guards for missing properties and update imports.
Tests — has-type / AOT
test/aot/has-type.test.ts
Add Intersect-related tests to detect File/File-like types in Intersect/Union compositions and Module.Import contexts.
Tests — dynamic
test/core/dynamic.test.ts
Add test verifying Union-type query schema is handled by getSchemaProperties() without crashing.
Tests — schema utils
test/schema/schema-utils.test.ts
New comprehensive tests for getSchemaProperties() and hasProperty() across Object, Union, Intersect, nested, and edge cases (including undefined/null inputs).
Tests — file uploads
test/type-system/files.test.ts
Add tests for file/files handling when file fields are wrapped in Union branches (single and multiple file scenarios via FormData).
Tests — query validator
test/validator/query.test.ts
Add tests for Union-based query schemas: repeated params mapping to arrays and numeric coercion within Union alternatives.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I hop through schemas, sniffing each nest,
Unions and intersects put me to the test,
I gather properties, tidy the fray,
Files and queries now find their way,
A happy rabbit hops off—hooray! 🐇✨

🚥 Pre-merge checks | ✅ 3
✅ 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 describes the main change: adding proper handling of t.Union/t.Intersection in property enumeration and validation checks across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

hasAdditionalProperties(schema))
},
get hasDefault() {
if ('~hasDefault' in this) return this['~hasDefault']
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Drive-by fix, not sure if it's something in my setup but typescript was complaining about this, the other methods had ! so I added it in

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/schema.ts`:
- Around line 1071-1091: getSchemaProperties currently merges properties from
schema.allOf and schema.anyOf but ignores schema.oneOf, causing inconsistent
behavior with helpers like hasProperty/hasType/hasRef/hasTransform; update
getSchemaProperties to include schema.oneOf in the same merge logic (e.g., treat
members = schema.allOf ?? schema.anyOf ?? schema.oneOf) so that properties from
oneOf unions are also collected when calling getSchemaProperties(schema).
🧹 Nitpick comments (1)
test/schema/schema-utils.test.ts (1)

86-89: Consider adding test coverage for oneOf schemas.

The hasProperty function handles oneOf (as tested on lines 145-154), but getSchemaProperties does not per the implementation in src/schema.ts. Consider adding a test to document the expected behavior when getSchemaProperties encounters a oneOf schema:

it('returns undefined for oneOf schema (not supported)', () => {
    expect(getSchemaProperties({ oneOf: [
        t.Object({ name: t.String() }),
        t.Object({ age: t.Number() })
    ]} as any)).toBeUndefined()
})

Alternatively, if oneOf should be supported, the implementation in src/schema.ts would need to be updated to handle it alongside allOf/anyOf.

@SaltyAom SaltyAom merged commit 69bc1c9 into elysiajs:main Feb 9, 2026
1 check passed
@coreh coreh deleted the union-intersection-handling branch February 9, 2026 04:37
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.

2 participants