class-validator: feat: @IsOptional should works only for undefined values
This code:
import { IsNotEmpty, IsOptional, IsString, validate } from 'class-validator';
import { plainToClass } from 'class-transformer';
const PATCH = 'patch';
const POST = 'post';
export class Test {
@IsOptional({ groups: [PATCH] })
@IsNotEmpty({ always: true })
@IsString()
name: string;
}
async function getValidationErrors(obj, group) {
return await validate(plainToClass(Test, obj), { groups: [group] });
}
describe('Test', () => {
it('should fail on post without name', async () => {
const errors = await getValidationErrors({}, POST);
expect(errors).not.toEqual([]);
});
it('should fail on post when name is undefined', async () => {
const errors = await getValidationErrors({ name: undefined }, POST);
expect(errors).not.toEqual([]);
});
it('should fail on post when name is null', async () => {
const errors = await getValidationErrors({ name: null }, POST);
expect(errors).not.toEqual([]);
});
it('should fail on post when name is empty', async () => {
const errors = await getValidationErrors({ name: '' }, POST);
expect(errors).not.toEqual([]);
});
it('should succeed on patch without name property', async () => {
const errors = await getValidationErrors({}, PATCH);
expect(errors).toEqual([]);
});
it('should fail on patch when name is undefined', async () => {
const errors = await getValidationErrors({ name: undefined }, PATCH);
expect(errors).not.toEqual([]);
});
it('should fail on patch when name is null', async () => {
const errors = await getValidationErrors({ name: null }, PATCH);
expect(errors).not.toEqual([]);
});
it('should fail on patch when name is empty', async () => {
const errors = await getValidationErrors({ name: '' }, PATCH);
expect(errors).not.toEqual([]);
});
});
gives the following results:
Am I missing something here?
Looking at the code of @IsOptional I see that it checks that the property is not undefined or null, that’s why the test for empty string is not failing, but in theory shouldn’t it check that this property exists on the object?
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 30
- Comments: 18 (6 by maintainers)
@vlapo How about something like an extra config option? The implementation I’ve got in my fork doesn’t break backwards compatibility (as the option defaults to
true, which is the default behaviour):The commit on the fork that adds this behaviour: https://github.com/se-internal/class-validator/commit/5ac9fa0c17ad43ecb0e8642675447b380a54139e
I use nestjs to validate a DTO from my controller
I have this
I send this body json
The expected behaviour:
The actual behaviour:
nullis ignored.If I have this DTO
Then
nullvalue throws CODE 400 which is expected.@IsOptional()should ignores only when the key is not passed in the request (aka.undefined) or an option to not ignoresnullvalue.We would love this as well, ether with a nullable flag, or as a separate set of decorators (although naming them can be difficult). @sam3d, your fork looks good to me, would you mind creating a PR?
I understand now. But as it is a breaking change I want to have more feedback from community.
Any update for this? really want to see this feature in next release @sam3d
any update on this one? And what about
PartialTypewhich is making all props optional? Can we somehow pass thisnullableparam toPartialTypeas well? 🤔In case anyone is interested, I’ve had the exact same issue and implemented this (alongside quite a few more decorators) in class-validator-extended, specifically
Optional()andNullable().How about keeping
@IsOptionalas-is and adding new decorators@IsNullableand@IsUndefinable. Any support for this?