Skip to content

Conversation

fabian-hiller
Copy link
Owner

FIx #983

Copy link

vercel bot commented Jan 13, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
valibot ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 22, 2025 0:03am

Copy link

pkg-pr-new bot commented Jan 13, 2025

Open in Stackblitz

npm i https://pkg.pr.new/valibot@1013

commit: d42d890

@andersk
Copy link
Contributor

andersk commented Jan 14, 2025

Seems mostly good, but optional defaults are broken:

> v.parse(v.object({ a: v.optional(v.string(), "foo") }), {})
{}

(expected { a: 'foo' })

@fabian-hiller
Copy link
Owner Author

fabian-hiller commented Jan 14, 2025

I think this is fixed now. I also added support for the nullish schema. This PR increases the bundle size of object by 100 bytes. If those 100 bytes fix all our problems, it should be fine.

The new behavior (these are breaking changes) of this PR is as follows:

  • optional no longer allows undefined as a value, it only allows missing object entries
  • Users must explicitly allow undefined by using undefinedable or union inside optional
  • object now distinguishes between missing and undefined values and only allows missing entries if the outer schema of an entry is optional or nullish
  • Any other schema will return an issue for missing object keys

Example:

const Schema = v.object({
  // Disallow missing keys
  key0: v.number(),                               // number
  key1: v.undefinedable(v.number()),              // number | undefined
  key2: v.nullable(v.number()),                   // number | null
  key3: v.unknown(),                              // unknown

  // Allow missing keys
  key4: v.optional(v.number()),                   // number
  key5: v.optional(v.undefinedable(v.number())),  // number | undefined
  key6: v.nullish(v.number()),                    // number | undefined | null
  key7: v.optional(v.unknown())                   // unknown
});

If we think this is the right solution for Valibot, I would also update these changes in looseObject, strictObject and objectWithRest. I would also update the tests to match the new behavior.

@fabian-hiller fabian-hiller self-assigned this Jan 14, 2025
@fabian-hiller fabian-hiller added bug Something isn't working enhancement New feature or request priority This has priority labels Jan 14, 2025
@fabian-hiller
Copy link
Owner Author

I have implemented your feedback and removed support for missing keys when using the nullish schema. The idea behind this change was to make our API more consistent. The only way to make an object entry optional now is to explicitly use optional as the outermost schema of the entry.

Furthermore, I refactored the implementation of the object schema and optimized its bundle size. These changes lowered the addition required bytes from about 100 to 77.

I think this PR is going in the right direction. My next steps are to apply these changes to the entire codebase and update our tests. Once this PR is done, I will probably create a GitHub discussion to explain these changes and reach out to the community and ask for feedback.

@fabian-hiller fabian-hiller changed the title Change object and optional to support exact optional props Change object and optional to support exact optional props Jan 16, 2025
@fabian-hiller
Copy link
Owner Author

Please discuss with use in #1022.

@fabian-hiller
Copy link
Owner Author

I followed @xcfox's idea: #1022 (comment)

@fabian-hiller fabian-hiller merged commit 81301f7 into main Jan 22, 2025
13 of 14 checks passed
@fabian-hiller
Copy link
Owner Author

Valibot v1.0.0-beta.13 is available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request priority This has priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Runtime behavior of optional/undefinedable doesn’t match TS with exactOptionalPropertyTypes
2 participants