-
Notifications
You must be signed in to change notification settings - Fork 46
DTO is not a class, all fields typed as optional #66
Comments
Can't really say much regarding the first issue, but in regards to the second issue where all properties are presented as being optional, Update: Actually zod's documentation requires you to set |
Thanks, @xrebelox - I changed the strict level and the second issue is gone. I never really ever had the need to enforce strict mode before, although it is recommended. I'm just stubborn. As for the first issue, I've found a fix: In the return validate(value, metatype.schema, createValidationException) As expected, if the validation passed, the object is returned. However, I kind of hacked the JS code directly, and I changed it to: const result = validate(value, metatype.schema, createValidationException)
return Object.assign(new metatype(), result) This creates a class instance of the same shape as the object. Since the DTO classes are created on-the-fly, this is safe to do. However, with a public library the choice on whether or not to transform the object to a class instance should be left to the end user, as it is in Nest's native The This begs the question on WHERE to set this user configurable value. The best option would be to add an options object directly to the interceptor's constructor like so: {
provide: APP_INTERCEPTOR,
useValue: new ZodSerializerInterceptor({ transform: true }),
} Of course, the interceptor's constructor has an const reflector = new Reflector() If you still prefer to inject it, there are ways to do that as well: {
provide: APP_INTERCEPTOR,
inject: [Reflector],
useFactory: (reflector: Reflector) =>
new ZodSerializerInterceptor(reflector, { transform: true }),
} I should note that for many use cases, the object is just fine and classes are not needed. However, this would be more of a semantic choice. If the type is defined as a certain class type, then the resulting value should conform to the class API specification including all the methods and accessors. This is why it should be the choice of the implementing party. I also notice there is no top-level module to initialize. This is also a good way to introduce user-specific configuration for all the moving parts to have access to. There's no contributing guide, so I'm curious as to the author's preferred protocols regarding PR's and such. I have loads of experience building NestJS libraries (all in-house libraries, but experience none the less), so I can make meaningful contributions to this project if it's welcome. Cheers. |
Hi.
First off, I'm happy there is a project using Zod instead of having to deal with class-validator. However, the
createZodDto
function does not create a class instance, but rather an object.I expected the function to return an instance of the class, so I can add additional methods and acessors, and be able to use them as well as
instanceof
calls downstream, as I've been accustomed to do usingclass-transfromer
. However, the value returned to the controller is a POJO.The above console statement produces
{ ... }, false
instead ofCreateEnvironmentDto { ... }, true
Another issue is that the object properties are all optional whereas the Zod schema has no optional properties. The LSP reports the shape of the object as such:
The actual type shown is this:
This keeps it from being useful for downstream API's where it should be assumed that all required properties are present in the DTO, which of course they are, but the LSP doesn't know that.
Using the most recent versions of this library and NestJS:
Hopefully there is a fix? I REALLY do not want to go back to using
class-validator
andvlass-transformer
which are just tedious to deal with.The text was updated successfully, but these errors were encountered: