Skip to content
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

z.discriminatedUnion and z.string.array throw SchemaError when submitting #516

Open
1 task done
endygower opened this issue Nov 24, 2024 · 4 comments
Open
1 task done
Labels
bug Something isn't working

Comments

@endygower
Copy link

endygower commented Nov 24, 2024

  • Before posting an issue, read the FAQ and search the previous issues.

Description
while I read that discriminatedUnion might be deprecated (here). however, this issue also reproducible using valibot.variant. I don't know whether valibot might be deprecated as well

I just so happen to write this using zod

Using z.discriminatedUnion and z.string().array() ie:

const schema = z.discriminatedUnion('type', [
	z.object({ type: z.literal('empty') }),
	z.object({ type: z.literal('extra'), options: z.string().array() })
])

it throws SchemaError on the server

However, it works when using z.string()

const schema1 = z.discriminatedUnion('type', [
	z.object({ type: z.literal('empty') }),
	z.object({ type: z.literal('extra'), options: z.string() })
])

Investigation
I did some investigation and found the responsible code is in this line

const defaultPropertyType =
typeof schema.additionalProperties == 'object'
? schema.additionalProperties
: ({ type: 'string' } as const);
for (const key of schemaKeys) {
const property: JSONSchema7Definition = schema.properties
? schema.properties[key]
: defaultPropertyType;

when parsing the form data, property is set as defaultPropertyType which is a { type: 'string' }

it doesn't consider that on top level union the schema is as follow and doesn't have properties

{
  $schema: ...,
  anyOf: [...]
}

then it will call parseSingleValue and the output will be

const data = new FormData()
data.append('options', '1')
data.append('options', '2')

imaginaryCallTo_parseFormData(data, ...)
// actual: { options: '2' }
// expected: { options: ['1', '2'] }

which will always fail the zod schema and later throws SchemaError

If applicable, a MRE
inside +page.server.ts you can change the schema use between schema (z.string.array) and schema1 (z.string)
https://www.sveltelab.dev/4adylfnc6g7pv98

@endygower endygower added the bug Something isn't working label Nov 24, 2024
@ciscoheat
Copy link
Owner

Thank you for a very thorough investigation, will hopefully fix this for the next release.

@ciscoheat
Copy link
Owner

Can you just confirm that the same thing happens when dataType is set to 'json' (or not) for the form?

@endygower
Copy link
Author

I just checked it sends the form correctly using dataType json.
I also updated the MRE if you want to try it yourself

Meanwhile, I will use dataType json while it is being fixed. thanks @ciscoheat

@ciscoheat
Copy link
Owner

Ok, then the "fix" will be to issue an error, since unions aren't allowed unless dataType is set to json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants