joiful icon indicating copy to clipboard operation
joiful copied to clipboard

"when" operator?

Open Ryanauger95 opened this issue 4 years ago • 4 comments

Is it possible to use the Joi "when" operator? In Joi, one can do:

Joi .string() .valid.apply(this, days) .required() .when("action", { is: "DELETE", then: Joi.string().optional(), otherwise: Joi.string().required() })

However, with jf, @(jf .string() .valid.apply(this, days) .required() .when("action", { is: "DELETE", then: jf.string().optional(), otherwise: jf.string().required() }))

I receive an error:

TypeError: jf.string(...).valid.apply(...).required(...).when is not a function

Ryanauger95 avatar Mar 03 '20 03:03 Ryanauger95

Sorry for the slow response.

It looks like we haven't implemented it, sorry. I also see we haven't implemented alternatives.

  • https://hapi.dev/module/joi/api/?v=15.1.1#anywhencondition-options
  • https://hapi.dev/module/joi/api/?v=15.1.1#alternatives---inherits-from-any

laurence-myers avatar Mar 20 '20 09:03 laurence-myers

Hi, is there a way to perform when with the current version? Is it possible via the any.custom() function?

My use case is to require one of two fields only. For example, I want to require email when phone is undefined, and vice versa.

dsc-leo avatar Jul 09 '20 07:07 dsc-leo

@dsc-leo Great idea to use custom()! I tried it out, and it works. 😁 That'll be a good workaround until joiful has the when() decorator proper.

Below is the test I wrote to verify this. I wrapped the when() in a convenience function. Note that one of the properties needs to use @lazy(), otherwise there's a circular reference between properties which causes joi/hoek to error.

    it('when(), via custom()', async () => {

        function exclusiveOr<T>(schema: Joi.AnySchema, propertyName: keyof T & string) {
            return schema.when(propertyName, {
                is: Joi.required(), // Check if the "other" property is defined
                then: Joi.forbidden(), // If so, the current schema "forbids" any value except undefined
                otherwise: Joi.required(), // Otherwise, the current schema rejects undefined values
            });
        }

        class ClassToValidate {
            @string().custom(({ schema }: { schema: Joi.Schema }) => exclusiveOr<ClassToValidate>(schema, 'phone'))
            public email?: string;

            @lazy(({ joi}) => exclusiveOr<ClassToValidate>(joi.string(), 'email'))
            public phone?: string;

            constructor() {}
        }

        let instance = new ClassToValidate();
        instance.email = '[email protected]';
        expect(instance).toBeValid();

        instance = new ClassToValidate();
        instance.phone = '555-5555';
        expect(instance).toBeValid();

        instance = new ClassToValidate();
        instance.email = '[email protected]';
        instance.phone = '555-5555';
        expect(instance).not.toBeValid();

        instance = new ClassToValidate();
        expect(instance).not.toBeValid();
    });

laurence-myers avatar Jul 11 '20 01:07 laurence-myers

I'll create a pr for this, if you didn't start working on it.

sshbio avatar Nov 01 '20 10:11 sshbio