Использование когда / альтернатив внутри когда - PullRequest
1 голос
/ 22 мая 2019

Мне нужно проверить схему с помощью joi.

Объект выглядит так:

  1. Существует обязательное свойство с именем "type", значения которого могут быть TYPE1, TYPE2, TYPE3.
  2. Если type === 'TYPE1', мы должны ожидать свойства one, two и three на одном уровне.
  3. Если type === 'TYPE2' мы должны ожидать свойства four, five и six на одном уровне.
  4. Если type === 'TYPE3', мы должны ожидать свойство subtype на том же уровне с возможными значениями A и B.
    • Если subtype === 'A', то мы должны ожидать свойства seven, eight, nine на том же уровне.
    • Если subtype === 'B', то мы должны ожидать свойства ten, eleven, twelve на том же уровне.

Вот что я придумал:

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);
}

Этот фрагмент доступендля тестирования здесь: https://repl.it/@AlessandroDe5/Joi-MCVE

Это показывает эту ошибку:

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.<anonymous> (/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)

Если я удаляю вложенный when (пункт 4, 4.1, 4.2), он работает без ошибок икурс отклоняет последние два объекта.

Я также пытался заменить when на alternatives:

.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(),
      }),
    ),
  },
);

Как и следовало ожидать, я получаю точно такую ​​же ошибку.

Есть ли способ как-нибудь выполнить задачу?

1 Ответ

0 голосов
/ 24 мая 2019

Я предлагаю другой подход с использованием Joi.alternatives () , таким образом, вы можете избежать вложенности при , поэтому ваша схема должна выглядеть следующим образом:

Joi.alternatives().try(
    Joi.object({
        type: Joi.string().valid('TYPE1').required(),
        one: Joi.string().required(),
        two: Joi.string().required(),
        three: Joi.string().required(),
    }),
    Joi.object({
        type: Joi.string().valid('TYPE2').required(),
        four: Joi.string().required(),
        five: Joi.string().required(),
        six: Joi.string().required(),
    }),
    Joi.object({
        type: Joi.string().valid('TYPE3').required(),
        subtype: Joi.string().valid('A', 'B')
    })
        .when(Joi.object({ subtype: 'A' }).unknown(), {
            then: Joi.object({
                seven: Joi.string().required(),
                eight: Joi.string().required(),
                nine: Joi.string().required(),
            }),
        })
        .when(Joi.object({ subtype: 'B' }).unknown(), {
            then: Joi.object({
                ten: Joi.string().required(),
                eleven: Joi.string().required(),
                twelve: Joi.string().required(),
            }),
        }),
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...