Why does order matter for alternatives().conditional() but not for any().when()?
Asked Answered
joi
G

0

0

Let there be:

const a = {
  b: Joi.alternatives().conditional("a", {
    is: "c",
    then: Joi.any(),
    otherwise: Joi.string().valid("d", "e").required(),
  }),
  a: Joi.string().valid(
    "a",
    "b",
    "c",
  ),
  c: Joi.bool(),
};
const b = {
  foo: Joi.alternatives().conditional("c", {
    is: true,
    then: Joi.any(),
    otherwise: Joi.alternatives().conditional("a", {
      switch: ["a", "b"].map((a, i) => ({
        is: a,
        then: Joi.alternatives().conditional("b", {
          switch: ["d"].map((b, i) => ({
            is: b,
            then: Joi.string().required(),
            ...(i === ["d"].length - 1 && { otherwise: Joi.any() }),
          })),
        }),
        ...(i === ["a", "b"].length - 1 && {
          otherwise: Joi.any(),
        }),
      })),
    }),
  }),
};

Validating the following data:

{ 
 "a": "a",
 "b": "d",
 "c": "true"
}

When using:

Joi.object({
  ...a,
  ...b,
});

Validation Passed

But when using:

Joi.object({
  ...b,
  ...a,
});

Validation Error: "foo" is required

Why does order of ...a and ...b matter here?


Let:

const a = {
  b: Joi.any().when("a", {
    is: "c",
    then: Joi.any(),
    otherwise: Joi.string().valid("d", "e").required(),
  }),
  a: Joi.string().valid("a", "b", "c"),
  c: Joi.bool(),
};
const b = {
  foo: Joi.any().when("c", {
    is: true,
    then: Joi.any(),
    otherwise: Joi.any().when("a", {
      switch: ["a", "b"].map((a, i) => ({
        is: a,
        then: Joi.any().when("b", {
          switch: ["d"].map((b, i) => ({
            is: b,
            then: Joi.string().required(),
            ...(i === ["d"].length - 1 && { otherwise: Joi.any() }),
          })),
        }),
        ...(i === ["a", "b"].length - 1 && {
          otherwise: Joi.any(),
        }),
      })),
    }),
  }),
};

Whether using ...a first or ...b first

Validation Passed

Why does order of ...a and ...b not matter here?

Grande answered 9/10, 2022 at 12:50 Comment(2)
From the docs: Note that alternatives.conditional() is different than any.when(). When you use any.when() you end up with composite schema of all the matching conditions while alternatives.conditional() will use the first matching schema, ignoring other conditional statements.Norven
@Norven I don't understand how this applies to this case. Can you please elaborate?Grande

© 2022 - 2024 — McMap. All rights reserved.