Мне нужно проверить схему с помощью joi
.
Объект выглядит так:
- Существует обязательное свойство с именем "type", значения которого могут быть
TYPE1
, TYPE2
, TYPE3
. - Если
type === 'TYPE1'
, мы должны ожидать свойства one
, two
и three
на одном уровне. - Если
type === 'TYPE2'
мы должны ожидать свойства four
, five
и six
на одном уровне. - Если
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(),
}),
),
},
);
Как и следовало ожидать, я получаю точно такую же ошибку.
Есть ли способ как-нибудь выполнить задачу?