Skip to content

Conversation

@truehazker
Copy link
Contributor

@truehazker truehazker commented Dec 5, 2025

Fixes #1597

parse() and safeParse() now return correct TypeScript types

  • Use Static<T> instead of T for return types in ElysiaTypeCheck and ModelValidator
  • Add T extends TSchema constraint to ModelValidator
  • Fix safeParse failure case from success: true to success: false
  • Add Extract<T, TSchema> for models getter type constraint
  • Add test cases for schema validator type inference

Summary by CodeRabbit

  • Type System Improvements

    • Tightened model and validator return types for stricter, more precise validation and parsing results.
    • Public validation APIs now surface a more accurate runtime data shape on successful parse/safeParse.
  • Tests

    • Added comprehensive unit tests covering parsing, safeParse success/failure, union/discriminated types, and type inference checks.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Walkthrough

Tightened public TypeScript types: parse/safeParse now return runtime value types via Static, ModelValidator generic constrained to T extends TSchema, and related validator interfaces adjusted; unit tests added for schema validation and type inference.

Changes

Cohort / File(s) Summary
Public API / index
src/index.ts
Narrowed computed models getter types: ModelValidator<Extract<Definitions['typebox'][K], TSchema>> replacing the broader schema entry type.
Schema validation types
src/schema.ts, src/types.ts
Imported Static from @sinclair/typebox. Updated ElysiaTypeCheck and ModelValidator signatures: parse() and safeParse() now return Static<T>; ModelValidator constrained to T extends TSchema; adjusted safeParse success/error unions and internal validator error handling references.
Tests
test/validator/schema-validator.test.ts
Added tests covering parse/safeParse success and failure paths, additional-properties behavior, discriminated union handling, and TypeScript type-inference assertions for validator returns.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify T extends TSchema doesn't break usages or public exports.
  • Confirm all public-facing signatures consistently use Static<T> and that consumer-facing types reflect runtime value shapes.
  • Inspect safeParse success/error discriminants and error payload shapes for correctness.
  • Run the new tests to ensure runtime behavior matches updated typings.

Poem

🐰✨ I hopped through types at break of day,
Swapped schema shells for Static's ray,
Now parse returns what values play,
Tests cheer, errors hush away—
A rabbit's joy in typed display! 🥕

Pre-merge checks and finishing touches

✅ 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 describes the main change: updating parse/safeParse return types to use Static for correct TypeScript type inference.
Linked Issues check ✅ Passed All objectives from issue #1597 are met: parse/safeParse use Static, ModelValidator has T extends TSchema constraint, Extract<T, TSchema> is applied to models getter, safeParse failure case corrected to success: false, and test cases added.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the schema validation type inference issue. No out-of-scope changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a020ad and 930dc2b.

📒 Files selected for processing (2)
  • src/schema.ts (5 hunks)
  • src/types.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/schema.ts (2)
src/index.ts (2)
  • Static (8245-8245)
  • mapValueError (8168-8168)
src/error.ts (1)
  • mapValueError (170-244)
src/types.ts (2)
src/index.ts (3)
  • ModelValidator (8220-8220)
  • TSchema (8245-8245)
  • Static (8245-8245)
src/type-system/index.ts (1)
  • TypeCheck (682-682)
🔇 Additional comments (6)
src/schema.ts (3)

9-10: LGTM! Import additions support the type refinements.

The Static import is essential for the new return type signatures, and TAnySchema is correctly imported for broader schema type handling.


38-63: Correct fix for type inference issue #1597.

The interface now uses Static<T> for Clean, parse, and the data field in safeParse's success branch, ensuring that consumers receive the resolved static value types rather than schema types. This directly addresses the reported problem where result.data was incorrectly typed as the schema representation.


997-997: Consistent error handling in dynamic validator paths.

The use of validator.Errors(v) aligns with the local variable scope in these dynamic schema validation paths, ensuring correct error extraction during safeParse operations.

Also applies to: 1159-1159, 1232-1232

src/types.ts (3)

2-2: LGTM! Type import correctly added.

The Static type import is necessary for the updated ModelValidator interface signatures.


2356-2356: Improved type constraint enhances API safety.

Adding T extends TSchema to ModelValidator prevents misuse with non-schema types and aligns with the ElysiaTypeCheck interface constraint, improving overall type safety.


2357-2365: Critical fix: Correct safeParse error branch and type refinements.

The changes implement the fix for issue #1597 by using Static<T> for return types, ensuring consumers receive resolved static value types. Key improvements:

  1. Parameter types: Correctly changed from T to unknown, as validators accept unknown input at runtime.
  2. Return types: parse and safeParse success cases now return Static<T> instead of T, resolving the type inference issue.
  3. Critical bug fix (Line 2361): The failure case now correctly sets success: false instead of success: true, preventing broken error handling logic.

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.

Copy link
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/schema.ts (1)

981-1006: safeParse catch blocks reference uninitialized compiled variable, causing ReferenceError

In three branches where local validator objects are constructed and returned early (before line 1279 where compiled is assigned), the safeParse catch blocks reference compiled.Errors(v). Since compiled remains uninitialized in these branches, accessing it triggers a temporal dead zone error.

The corresponding parse methods correctly use validator.Errors(v), confirming the fix. Replace compiled.Errors(v) with validator.Errors(v) in:

  • Line 988 (standard + extra validators branch)
  • Line 1158 (dynamic TypeBox branch)
  • Line 1229 (dynamic standard-schema branch)
🧹 Nitpick comments (1)
test/validator/schema-validator.test.ts (1)

62-165: safeParse tests correctly pin the new result shape and type inference

The safeParse tests validate:

  • success branch: success: true, populated data, error === null.
  • failure branch: success: false, data === null, error and errors present.
  • Static-style inference via explicit number/string annotations on result.data fields.

One optional improvement: if you want to assert union inference more strongly, you could add a compile-time-only check like assigning messageResult.data to a variable typed as the union’s static type (e.g. typeof eventPayload.static) so the compiler will fail if it ever regresses.

If you want, I can sketch a small extra union-inference test that relies purely on TypeScript’s type checking without affecting runtime.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07b449a and 9a020ad.

📒 Files selected for processing (4)
  • src/index.ts (1 hunks)
  • src/schema.ts (2 hunks)
  • src/types.ts (2 hunks)
  • test/validator/schema-validator.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
test/validator/schema-validator.test.ts (1)
src/schema.ts (1)
  • getSchemaValidator (742-1399)
src/schema.ts (1)
src/index.ts (1)
  • Static (8245-8245)
src/types.ts (2)
src/index.ts (3)
  • ModelValidator (8220-8220)
  • TSchema (8245-8245)
  • Static (8245-8245)
src/type-system/index.ts (1)
  • TypeCheck (682-682)
🔇 Additional comments (5)
test/validator/schema-validator.test.ts (1)

6-60: Parse tests exercise key behaviors and match current validator semantics

The parse suite covers happy-path, additionalProperties toggling, and invalid data cases in a way that aligns with getSchemaValidator’s current behavior; this is a good regression net for the new Static-based typings as well.

src/index.ts (1)

453-462: models getter typing now correctly respects ModelValidator<T extends TSchema>

Switching to ModelValidator<Extract<Definitions['typebox'][K], TSchema>> is consistent with the new T extends TSchema constraint on ModelValidator and with how definitions.typebox is populated at runtime (TypeBox-only). The change is type-level only and shouldn’t affect behavior; it just prevents accidentally threading non-TSchema entries into ModelValidator.

If, in the future, Definitions['typebox'] can contain non-TSchema entries, consider an alias-style mapped type that drops those keys entirely instead of effectively giving them ModelValidator<never>, but that’s not necessary with the current design.

Please make sure DefinitionBase['typebox'] is indeed constrained to TypeBox schemas in your intended public surface so that this Extract remains sound.

src/schema.ts (1)

2-11: ElysiaTypeCheck now correctly exposes Static-based value types from TypeBox

Importing Static and updating ElysiaTypeCheck<T extends TSchema> so that:

  • Clean returns Static<T>,
  • parse returns Static<T>,
  • the safeParse success variant has data: Static<T>,
    brings the public typing in line with how validators are actually produced (Value.Decode, TypeCompiler.Compile, and createMirror all operate on the static value shape, not the schema AST). This directly addresses the issue where parse/safeParse previously surfaced TObject<...>-like schema types instead of { id: number; name: string }-style runtime values, and it matches how the new tests use result.data.id and result.data.name as primitives.

Given that ElysiaTypeCheck extends Omit<TypeCheck<T>, 'schema'> and defines these methods itself, the narrowing to Static<T> here is sound with respect to TypeBox’s generics.

Please run tsc against a few representative validators (object, union, transform) to confirm that parse/safeParse now resolve to the same Static<T> shape as TypeBox.Static<typeof schema>.

Also applies to: 38-47

src/types.ts (2)

2-2: LGTM!

The Static import is correctly added to support the return type changes in ModelValidator.


356-366: Core type fixes look correct.

The changes properly address issue #1597:

  • Static<T> for return types ensures parse and safeParse return the resolved value type (e.g., { id: number; name: string }) instead of the schema type
  • The success: false fix in the failure branch corrects what was a bug (previously typed as true)
  • The T extends TSchema constraint properly restricts the generic

One observation: the parameter type a: T takes the schema type, but semantically parse/safeParse receive values to validate (should be unknown). TypeBox's own TypeCheck.Decode uses unknown for input. This appears to be a pre-existing pattern, but worth verifying that it doesn't cause type inference issues in practice.

@SaltyAom
Copy link
Member

SaltyAom commented Dec 9, 2025

I decided to roll my own code because getSchemaValidator should also works with Standard Schema as well which #1598 doesn't support

@SaltyAom SaltyAom closed this Dec 9, 2025
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.

safeParse() and parse() return schema type instead of static value type

2 participants