zod
zod copied to clipboard
Enums should support an omit method
Example of what has to be done right now:
const a = z.nativeEnum( { a: 1, b: 2 } as const )
const b = z.nativeEnum( Remeda.omit( a._def.values, [ 'a' ] ) )
b._def.values.b // works
b._def.values.a
// ^
// Property 'a' does not exist on type 'Omit<{ readonly a: 1; readonly b: 2; }, "a">'.
I'm not sure how to do it with zod enums actually.
This issue would be asking for native and zod enums though to support an omit method.
Here's how you do it with zod enums
const foo = z.enum( [ 'a', 'b' ] )
type ExcludeA = Exclude<z.infer<typeof foo>, 'a'>
// type ExcludeA = "b"
const bar = z.enum(
foo.options.filter( x => x !== 'a' ) as [ ExcludeA, ...ExcludeA[] ]
)
bar.enum.b // works
bar.enum.a
// ^
// Property 'a' does not exist on type 'Values<["b", ..."b"[]]>'.
There's an argument that this should be a top-level z.omit
utility, which has been suggested elsewhere.
const a = z.nativeEnum( { a: 1, b: 2 } as const )
const omitted = z.omit(a, z.literal(2));
Once we have a ZodEmit
schema type, we can add a global .omit
method on the base ZodType.
@colinhacks in your example you're omitting by value?
Once we have a ZodEmit schema type, we can add a global .omit method on the base ZodType.
How about generic static .omit
function AND method helpers too?
you're omitting by value?
The inferred type of this this enum is 1 | 2
so you'd omit a literal 2
to remove that option.
const a = z.nativeEnum( { a: 1, b: 2 } as const )
// 1 | 2
You could also do this:
const a = z.nativeEnum({ a: 1, b: 2 } as const);
const omitted = z.omit(a, z.literal(a.values.b));
AND method helpers too?
Yep that's what I mean by "add the .omit
method on the base ZodType
". This would add the .omit
method to all Zod schemas.
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.
Pleae re-open
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.
Pleae re-open
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.
Pleae re-open
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.
Please re-open
I was able to get this working using .refine
. Of course it could be easier, but it was good enough for my solution.
import { z } from 'zod';
enum Status {
todo = 'todo',
inProgress = 'inProgress',
completed = 'completed',
}
const notCompleted = z
.nativeEnum(Status)
.refine((status): status is Exclude<Status, Status.completed> => status !== Status.completed);
type NotCompleted = z.infer<typeof notCompleted>;
// ^? type NotCompleted = Status.todo | Status.inProgress;
ZodEnum
now has a .exclude()
method that implements this behavior as of Zod 3.21.
Top level z.omit
is probably not going to happen so I'm going to close.
Would it be possible to add the .exclude()
method also in ZodNativeEnum
?
I have a case where I need to exclude from a prisma enum a specific value:
const validationSchema = z.object({
...
type: z.nativeEnum(Prisma.AutomationType),
...
});
Currently I can recreate the native enum schema with a ZodEnum
, and then call .exclude()
on it, but my AutomationType
would grow huge so I would like a simpler approach.