Skip to content

v4: cannot use empty object as default for schema with defaults - regression? #4308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
radiosilence opened this issue May 2, 2025 · 1 comment

Comments

@radiosilence
Copy link

radiosilence commented May 2, 2025

In v3, you could do:

import { z } from 'zod';

const MyChildSchema = z.object({
  num: z.number().default(1),
  text: z.string().default('blah'),
});

const MyParentSchema = z.object({
  child: MyChildSchema.default({}),
});

This made doing deeply nested defaults with overrides very simple.

In v4, you get a TypeScript error on the child: MyChildSchema.default({}), line:

ts: No overload matches this call.
  Overload 1 of 2, '(def: { num: number; text: string; }, params?: string | { error?: undefined; } | undefined): ZodDefault<ZodObject<{ num: ZodDefault<ZodNumber>; text: ZodDefault<ZodString>; }, {}>>', gave the following error.
    Argument of type '{}' is not assignable to parameter of type '{ num: number; text: string; }'.
      Type '{}' is missing the following properties from type '{ num: number; text: string; }': num, text
  Overload 2 of 2, '(def: () => { num: number; text: string; }, params?: string | { error?: undefined; } | undefined): ZodDefault<ZodObject<{ num: ZodDefault<ZodNumber>; text: ZodDefault<ZodString>; }, {}>>', gave the following error.
    Argument of type '{}' is not assignable to parameter of type '() => { num: number; text: string; }'.
      Type '{}' provides no match for the signature '(): { num: number; text: string; }'.

This feels like unwanted behaviour, because surely the defaults mean that the empty object {} would be valid (IE uses child's default).

If there's a better way to do this I am interested.

@radiosilence radiosilence changed the title v4: cannot assign empty object to schema with defaults - regression? v4: cannot empty object as default for schema with defaults - regression? May 2, 2025
@radiosilence radiosilence changed the title v4: cannot empty object as default for schema with defaults - regression? v4: cannot use empty object as default for schema with defaults - regression? May 2, 2025
@bobhigs
Copy link

bobhigs commented May 5, 2025

I just ran into this myself. I use default({}) all time time. It looks like the issue is that zod v3 default(...) was defined using the Input type:

default(def: util.noUndefined<Input>): ZodDefault<this>;

While in v4 the default(...) is defined using this output type in both zod and @zod/mini:

default(def: util.NoUndefined<core.output<this>>, params?: string | core.$ZodDefaultParams): ZodDefault<this>;

export function _default<T extends SomeType>(
innerType: T,
defaultValue: util.NoUndefined<core.output<T>> | (() => util.NoUndefined<core.output<T>>),
params?: string | core.$ZodDefaultParams
): ZodMiniDefault<T> {

I believe the version is zod v3 is correct and that this should be switch back to the input type

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

No branches or pull requests

2 participants