#Zod "number" enum?

1 messages · Page 1 of 1 (latest)

digital voidBOT
#
drwarpman#0

Preview:```ts
import {z} from "zod"

const options = [1, 2, 3] as const

const SCHEMA = z.enum(options)

type Options = z.infer<typeof SCHEMA>
//^?```

tight escarp
#

What would I have to change to make this work? Zod enums only work with strings obviously.

#
SCHEMA.parse(1) // ok
SCHEMA.parse("1")  // bad
SCHEMA.parse(0) // bad

and:
type Options should be 1 | 2 | 3

restive kernel
#

You can use z.union with z.literal.

tight escarp
#

But what if I got hundreds of them?

#

1,2,3,4,5,6,7,8,9...

restive kernel
#

You can Array#map over them.

digital voidBOT
#
drwarpman#0

Preview:```ts
import {z} from "zod"

const options = [1, 2, 3] as const

const literals = options.map(option =>
z.literal(option)
)

const SCHEMA = z.union(literals)

type Options = z.infer<typeof SCHEMA>
//^?```

tight escarp
restive kernel
#

Ah yeah z.union type is a bit too harsh.

digital voidBOT
#
nonspicyburrito#0

Preview:```ts
import {z} from "zod"

const options = [1, 2, 3] as const

const foo = z.union([
z.never(),
z.never(),
...options.map(value => z.literal(value)),
])

type Foo = z.infer<typeof foo>
// ^?```

restive kernel
#

Here's one way to do it.

tight escarp
#

😳

restive kernel
#

Alternatively you can just assert the map result but eh.

digital voidBOT
#
nonspicyburrito#0

Preview:```ts
import { z } from 'zod'

const toZodLiterals = <const T extends readonly z.Primitive[]>(options: T) =>
options.map((value) => z.literal(value)) as {
[K in keyof T]: z.ZodLiteral<T[K]>
}

const options = [1, 2, 3] as const

const foo = z.union(toZodLiterals(options))
...```

restive kernel
#

A utility function like that could also work.

tight escarp
#

I feel so bad making utility functions when I only have one place where I would use it across the entire app :/

restive kernel
stone mesa
#

@tight escarp This seems cleaner to me:

const options = [1, 2, 3] as const

type OptionValue = (typeof options)[number]

const foo = z.custom<OptionValue>(val => (options as readonly unknown[]).includes(val));