Skip to content

fix(experimental): allow partial object defaults with optional - #198

Merged
ping-maxwell merged 1 commit into
better-auth:experimentalfrom
ping-maxwell:fix/experimental-object-optional-default
Sep 1, 2026
Merged

fix(experimental): allow partial object defaults with optional#198
ping-maxwell merged 1 commit into
better-auth:experimentalfrom
ping-maxwell:fix/experimental-object-optional-default

Conversation

@ping-maxwell

Copy link
Copy Markdown
Collaborator

Summary

v.object(shape, { optional: true, default: {} }) was failing whenever the shape had required fields, and TypeScript blamed optional even though the real mismatch was the empty default. Object defaults are now typed as partial inputs, so a parent being optional/defaulted does not force every child to appear in the default.

Also put optional on the shared type options so helpers like v.number({ optional: true }) accept it without falling through to an overload that pretends the property does not exist.

Parent `v.object(..., { optional: true, default: {} })` no longer requires
every nested field to be listed in the default. Also expose `optional` on
base type options so helpers like `v.number({ optional: true })` accept it
cleanly.
@pkg-pr-new

pkg-pr-new Bot commented Sep 1, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/better-call@198

commit: 24dd0c3

@ping-maxwell
ping-maxwell merged commit 933ee4a into better-auth:experimental Sep 1, 2026
6 checks passed
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

The PR widens experimental schema helper options and permits partial defaults for object schemas.

  • Adds shared support for optional in helper option types.
  • Makes object defaults partial and adds type-level coverage for optional primitives and nested object defaults.

Confidence Score: 3/5

The PR should not merge until partial object defaults and boolean-valued optional options preserve an output type consistent with runtime validation.

The changed overloads accept an empty default that can fail when required children are validated, and they infer a non-optional output for dynamic optional flags that can return undefined at runtime.

Files Needing Attention: packages/experimental/src/schema.ts, packages/experimental/src/schema-dx.test.ts

Fix all with Greploop Fix All in Cursor Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "fix(experimental): allow partial object ..." | Re-trigger Greptile

* fine at the type level - parent `optional` / `default` must not
* demand that every required child be listed in the default.
*/
type ObjectDefault<S> = DefaultInput<Partial<ArgsShape<S>>>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Partial defaults fail validation

When a partial object default omits a required child without its own default, the new type accepts the declaration, but runtime validation checks that child as undefined, causing validation to throw instead of returning the declared object output.

Knowledge Base Used: Validation and schema contracts

Fix in Cursor Fix in Codex Fix in Claude Code


export type TypeOptions<T, O> = {
transform?: (value: T) => O;
/** Accepted on every helper; overloads refine the output when `true`. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Dynamic optional flags misinfer output

When a caller passes a non-literal boolean such as v.number({ optional: condition }) and its value is true, the fallback overload infers a non-optional output while runtime validation returns undefined, allowing downstream code to use an absent value as an unconditional primitive.

Fix in Cursor Fix in Codex Fix in Claude Code

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