Comments (8)
z.nativeEnum(MyEnum)
Worked for my with a prisma db schema generated enum
from zod.
when you find your answer looking for the problem in google and can't remember how you knew the answer a year back.
Back to the future debugging LOL
from zod.
for future googlers – it's z.nativeEnum
, not z.NativeEnum
https://zod.dev/?id=native-enums
from zod.
FWIW the lack of support for enums is what sent me into the arms of io-ts having tried zod first, although not a hugely satisfying fix there: gcanti/io-ts#216 (comment). Requires an additional helper needs to be invoked like:
fromEnum<EnumType>('EnumType', EnumType)
However, once it's done you are allowed to forget about it forever.
I will definitely consider using a syntax like the one you recommended
It sounds like you are seeing this as syntactic sugar. What I'd like is the inferred type to be exactly the enum type I pass in.
The problem with defining the enum as you describe is that the inferred string union is not assignable to the existing enum. So you still need to convert the union to the enum via reverse lookup EnumType[value]
. This gets ugly if you have functions taking deeply nested types with enum values present.
Simple support for this seems on-brand for your develop-experience focus and a differentiator with io-ts :)
from zod.
=== UPDATE: the syntax described below is no longer accurate ===
I implemented a way to declare enums, but it's a bit different from the API you suggested. I will definitely consider using a syntax like the one you recommended at some point though.
Current usage:
const MyEnum = z.enum([
z.literal('Bar'),
z.literal('Baz'),
z.literal('Foo')
]);
MyEnum.parse('Bar'); // => Bar
MyEnum.parse('LOL'); // => throws
Type inference works as expected:
type MyEnum = z.TypeOf<typeof MyEnum>
// => "Bar" | "Baz" | "Foo"
And for good measure you can get autocomplete on your enum values with the .Values
variable like so:
const val = MyEnum.Values.Bar;
type MyEnumValues = MyEnum.Values;
// => { Bar: "Bar", Baz: "Baz", Foo: "Foo" }
I'm about to go out of town, but I will eventually implement a syntax more similar to yours, probably called .fromEnum()
:
enum Foo {
BAR = 'BAR',
BAZ = 'BAZ'
}
let e = z.fromEnum(Foo);
e.parse("LOL"); // throws
Closing this in the meantime.
from zod.
@silasdavis I appreciate the feedback. 👍
In my opinion Zod's current approach is much more developer-friendly, though I understand that it's annoying to rewrite a bunch of enums in a non-language construct.
For starters, I hate normal "numeric" enums with a passion. Defining a mapping from string keys to numeric values that hides the actual values and is determined exclusively by key ordering is a recipe for disaster. gcanti agrees with me on this: gcanti/io-ts#216 (comment)
Since I expect many people will use Zod to validate "real data" before writing it to their database, etc, I wanted to help users avoid that category of bugs.
The io-ts approach is doubly duplicative. You have redundancy in your "real" enum definition
enum MyEnum {
Tuna = "tuna",
Trout = "trout
}
and triple-redundancy in your io-ts schema definition
fromEnum<Thing>("Thing", Thing);
compared to
z.enum(['Tuna','Trout']);
from zod.
Moreover there appears to be a bug in the @geekflyer fromEnum
implementation where it will incorrectly accept one of the enum's keys as a valid value. I haven't tested this so apologies if I'm wrong about this.
enum Thing {
FOO = "foo",
BAR = "bar"
}
const ThingCodec = fromEnum<Thing>("Thing", Thing);
ThingCodec.decode('foo')
// passes validation correctly
ThingCodec.decode('FOO')
// passes validation incorrectly
So this solution doesn't really give you the behavior you want anyway.
from zod.
tl;dr using enums is not my choice to make, the inferred type for a schema has values (where an enum value should be) that are not assignable to enum values, meaning they cannot be passed to functions that expect enums.
For starters, I hate normal "numeric" enums with a passion.
I am not a great fan of enums either, the subtleties of const and non-const sprint to mind. The point is you often do not control the definition of types on which you depend. Either they are owned by code you do not control or are generated by some tooling that is hard to change (e.g. OpenAPI spec). Despite their short-comings they are part of a language with at the very least highly suggestive semantics, and outside of typescript code where const literals stand in for enums very well I'm not sure I would agree with an outright ban of enums. Moreover I'd question if a schema library should be calling the shots here.
annoying to rewrite a bunch of enums in a non-language construct
The io-ts approach is doubly duplicative.
It's not that it is annoying (it is, but I can deal with that), indeed as you point out the option I am currently using is not pretty. What is a deal-breaker for me is that if I have a structure containing enums like:
type Foo = {
Inner: {
Bar: EnumType
}
Baz: EnumType
}
The schema inferred type will be something like:
type InferredFoo = {
Inner: {
Bar: 'ValueA' | 'ValueB'
}
Baz: ValueA' | 'ValueB'
}
I cannot pass InferredFoo
to a function that expects Foo
, but I mean to express Foo
with my schema.
I could define a function realFoo(foo: InferredFoo): Foo
but that is excessively burdensome. I need to be able to describe the shape of the data I actually have with schema within the confines of Typescripts Javascripty enums.
You have redundancy in your "real" enum definition
As above, let's assume that someone else has inflicted that on me.
So this solution doesn't really give you the behavior you want anyway.
I actually stopped paying attention when it compiled :) but I've just written a test case and it does not exhibit the behaviour you describe. It's acting over the values of the enum.
from zod.
Related Issues (20)
- question: can I generate a zeroed out object from a schema with validation? HOT 1
- Reversing nullable on schema HOT 1
- feat: single method to comine `.unwrap().unwrap()` HOT 1
- zod a field whose type is jsonLogic.RulesLogic. From type to zod HOT 1
- Issue with inferring types from pipes. HOT 6
- `z.literal` message not customizable HOT 3
- Add Search Bar Functionality to zod HOT 2
- Inability to retrieve keys from z.nativeEnum type
- Large declaration files for flattened zod schema HOT 1
- Can not use branded enum options HOT 1
- Passing `RawCreateParams` to `z.tuple()` doesn't apply to all errors generated by `z.tuple()`. HOT 3
- Organizational GitHub Account & Profile HOT 1
- z.merge not inferring types properly HOT 3
- Looking for a way to reuse the same schema with `.merge` HOT 1
- Using .default with z.object doesn't do anything, and neither does .required if z.object has defaults
- New Restriction in .pick()/.omit() restrict using of dynamic property in the object HOT 1
- Intersection of object and record fails if function is used as a value for both
- multipleOf acts wrong starting with 7 decimal places HOT 3
- [FEAT] add "afterRefine" method HOT 2
- lazy doesn't compile when used with default HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zod.