title: Using when/alternatives inside when
body: <p>I need to validate a schema with <code>joi</code>.</p>
  
  <p>The object is like this:</p>
  
  <ol>
  <li>There is a required property named "type" whose values can be <code>TYPE1</code>, <code>TYPE2</code>, <code>TYPE3</code>.</li>
  <li>If <code>type === 'TYPE1'</code>, we must expect properties <code>one</code>, <code>two</code> and <code>three</code> at the same level.</li>
  <li>If <code>type === 'TYPE2'</code>, we must expect properties <code>four</code>, <code>five</code> and <code>six</code> at the same level.</li>
  <li>If <code>type === 'TYPE3'</code>, we must expect a <code>subtype</code> property at the same level, with possible values <code>A</code> and <code>B</code>.
  
  <ul>
  <li>If <code>subtype === 'A'</code>, then we must expect properties <code>seven</code>, <code>eight</code>, <code>nine</code> at the same level.</li>
  <li>If <code>subtype === 'B'</code>, then we must expect properties <code>ten</code>, <code>eleven</code>, <code>twelve</code> at the same level.</li>
  </ul></li>
  </ol>
  
  <p>This is what I came up with:</p>
  
  <pre class="lang-js prettyprint-override"><code>import { object, string, validate } from 'joi';
  
  const obj1 = { // valid
    type: 'TYPE1',
    one: '01',
    two: '02',
    three: '03',
  };
  const obj2 = { // valid
    type: 'TYPE2',
    four: '04',
    five: '05',
    six: '06',
  };
  const obj3 = { // valid
    type: 'TYPE3',
    subtype: 'A',
    seven: '07',
    eight: '08',
    nine: '09',
  };
  const obj4 = { // valid
    type: 'TYPE3',
    subtype: 'B',
    ten: '10',
    eleven: '11',
    twelve: '12',
  };
  
  const joiSchema = object({
    // point 1
    type: string().valid('TYPE1', 'TYPE2', 'TYPE3').required(),
  })
  .when(
    // point 2
    object({ type: 'TYPE1' }).unknown(),
    {
      then: object({
        one: string().required(),
        two: string().required(),
        three: string().required(),
      }),
    },
  )
  .when(
    // point 3
    object({ type: 'TYPE2' }).unknown(),
    {
      then: object({
        four: string().required(),
        five: string().required(),
        six: string().required(),
      }),
    },
  )
  .when(
    // point 4
    object({ type: 'TYPE3' }).unknown(),
    {
      then: object(
        // if type === 'TYPE3', check for one of those schemas
        {
          // point 4
          subtype: string().valid('A', 'B'),
        },
      ).when(
        // point 4.1
        object({ subtype: 'A' }).unknown(),
        {
          then: object({
            seven: string().required(),
            eight: string().required(),
            nine: string().required(),
          }),
        },
      ).when(
        // point 4.2
        object({ subtype: 'B' }).unknown(),
        {
          then: object({
            ten: string().required(),
            eleven: string().required(),
            twelve: string().required(),
          }),
        },
      ),
    },
  );
  
  const result1 = validate(obj1, joiSchema);
  console.log('Validating obj1')
  if (result1.error) {
    console.error(result1.error.message);
  }
  
  const result2 = validate(obj2, joiSchema);
  console.log('Validating obj2')
  if (result2.error) {
    console.error(result2.error.message);
  }
  
  const result3 = validate(obj3, joiSchema);
  console.log('Validating obj3')
  if (result3.error) {
    console.error(result3.error.message);
  }
  
  const result4 = validate(obj4, joiSchema);
  console.log('Validating obj4')
  if (result4.error) {
    console.error(result4.error.message);
  }
  </code></pre>
  
  <p>This snippet is available for testing here: <a href="https://repl.it/@AlessandroDe5/Joi-MCVE" rel="nofollow noreferrer">https://repl.it/@AlessandroDe5/Joi-MCVE</a></p>
  
  <p>It is showing this error:</p>
  
  <pre><code>AssertionError [ERR_ASSERTION]: Cannot merge type object with another type: alternatives
      at new AssertionError (internal/errors.js:315:11)
      at Object.exports.assert (/home/runner/node_modules/hoek/lib/index.js:559:11)
      at internals.Object.concat (/home/runner/node_modules/joi/lib/types/any/index.js:148:14)
      at internals.Alternatives.when (/home/runner/node_modules/joi/lib/types/alternatives/index.js:131:52)
      at index.ts:52:6
      at Script.runInThisContext (vm.js:65:33)
      at startRepl (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:157:12)
      at Object.&lt;anonymous&gt; (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:66:1)
      at Module._compile (internal/modules/cjs/loader.js:654:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
  </code></pre>
  
  <p>If I remove the nested <code>when</code> (point 4, 4.1, 4.2) it works without errors and of course rejects the last two objects.</p>
  
  <p>I also tried replacing <code>when</code> with <code>alternatives</code>:</p>
  
  <pre class="lang-js prettyprint-override"><code>.when(
    // point 4
    object({ type: 'TYPE3' }).unknown(),
    {
      then: alternatives().try(
        object({
          subtype: string().valid('A'),
          seven: string().required(),
          eight: string().required(),
          nine: string().required(),
        }),
      ).when(
        object({
          subtype: string().valid('B'),
          ten: string().required(),
          eleven: string().required(),
          twelve: string().required(),
        }),
      ),
    },
  );
  </code></pre>
  
  <p>As one could expect I get the exact same error.</p>
  
  <p>Is there a way accomplish the task somehow?</p>