-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add z.select (similar to z.enum but accepting anything as options) #2318
Comments
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This is a valid issue with a reasoning and having a PR. |
Alas, this has been stuck for a year now. Whoever is interested, I recommend trying valibot which has import * as v from "valibot"
const options = await getOptions(); // string[] or number[] or even any[]
const schema = v.picklist(options); // works!
const input = v.parse(schema, data) // input is guaranteed to be one of options, properly typed |
Thanks for the great PR and analysis @IlyaSemenov. I'm wary of a generic There are a couple solutions I prefer here. 1. Support for numbers and symbols in
|
Problem
Imagine I have a schema that validates a value to be one of the predefined integers. Like when a user chooses the length of the secret key to be either 512, 1024 or 2048 bits (just random example). Naturally, I would imagine there was a Zod schema for that... like
z.enum([512, 1024, 2048])
? Unfortunately, that doesn't work, asz.enum
only accepts string values.Another scenario is where the list of options is coming from the variable and is only known in runtime:
Current workaround
One can use
z.union([z.literal(512), z.literal(1024), z.literal(2048)]
but it's cumbersome, it's arguably slow (as it validates each sub-schema independently) and it doesn't work with option values other than strings and numbers.Considered solutions
At first, I was thinking that
z.enum
could be extended to allow any list of anything as valid options (#2317). That is not a viable approach asz.enum(...).enum
will break then (thanks @igalklebanov for pointing to that).Another suggested approach was to extend
z.union
to accept literals. I don't like that for two reasons:z.union
is advertised as an aggregating schema builder. Mixing unrelated concepts (nested schemas vs. literals) should be avoided.z.union
were to accept arbitrary options but treat zod schemas separately, then zod schemas themselves would not be valid options to choose from. (Not that it's a huge tragedy but that is a limitation that could be avoided).Suggested approach
I propose to add
z.select
which will be basicallyz.enum
withoutschema.enum
but accepting anything as the list of options (not even necessarily primitives):In fact,
z.enum
will probably be a subclass ofz.select
in that case (they will shareschema.options
and probably the actual validation implementation).The resulting type could be derived from the options with
ElementOf<...>
recipe.The text was updated successfully, but these errors were encountered: