zod
zod copied to clipboard
Ability to "name" an enum
Consider this Zod-to-Nexus function:
export const enumType = <
S extends
| z.ZodNativeEnum<any>
| z.ZodEnum<[string, ...string[]]>
| z.ZodUnion<[z.ZodLiteral<string>, ...z.ZodLiteral<string>[]]>
>(
schema: S,
config?: { name: string; case?: 'camel' | 'snake' }
) => {
const name = config?.name ?? schema._def.typeName
const enumifyThis = enumify(config?.case ?? 'snake')
const members =
'options' in schema._def
? // union case
schema._def.options.map((_) => _._def.value).map(enumifyThis)
: // enum case
Array.isArray(schema._def.values)
? schema._def.values.map(enumifyThis)
: values(schema._def.values)
.map((_) => String(_))
.map(enumifyThis)
return Nexus.enumType({
name,
members,
})
}
When using it today it is not possible to capture the enum name so we get code like this:
const ExternalErrorDatabaseKind = z.enum([
'IntrospectionFailure',
'NotEmpty',
'PushSchemaFailure',
'SeedFailure',
])
NexusZod.enumType(ExternalErrorDatabaseKindEnum, {
name: 'ExternalErrorDatabaseKind',
})
What I wish we could do is just:
NexusZod.enumType(ExternalErrorDatabaseKindEnum)
Which would I guess be powered by a new Zod method on enums like this:
const ExternalErrorDatabaseKind = z.enum([
'IntrospectionFailure',
'NotEmpty',
'PushSchemaFailure',
'SeedFailure',
]).name(`ExternalErrorDatabaseKind`)
Or maybe unify name and description under the concept of "metadata":
const ExternalErrorDatabaseKind = z.enum([
'IntrospectionFailure',
'NotEmpty',
'PushSchemaFailure',
'SeedFailure',
]).metadata({ name: `ExternalErrorDatabaseKind`, description: 'foobar' })
I'm still hesistant to add additional metadata beyond the .describe
method I implemented after our earlier discussion: https://github.com/colinhacks/zod/issues/677 Though it does seem like that would be adequate?
Even with a Zod method for naming a schema, there wouldn't be a statically detectable difference between z.enum([...])
and z.enum(...).name('MyEnum')
. Which means there would be no way to prevent users at compile time from doing NexusZod.enumType(z.enum([...]))
. I guess this would just throw at runtime?
I'm still hesistant to add additional metadata beyond the .describe method
Yeah I think that's quite reasonable! While describe
is genuine information not found elsewhere name
looks less like that. So yeah, not sure this belongs in here.
I guess this would just throw at runtime?
Yeah guess it would have to. I suspect baking the "named"ness of a zod type would add a big breaking change for something that looks to have dubious value.
Maybe other use-cases for "naming" types can be found. For example maybe schemas with names could be leveraged for improved error messages.
But on the whole it seems like an awkward feature request right now.
Maybe the ability to attach metadata would be another solution without baking in any assumptions.
const ExternalErrorDatabaseKind = z.enum([
'IntrospectionFailure',
'NotEmpty',
'PushSchemaFailure',
'SeedFailure',
]).metadata({ foo: '', bar: false, qux: 3 })
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.