The @hapi/joi documentation is not very clear on this (at v17.1.0). The resulting schemas have the same value, and they validate the same. Looking at the source, Object type is a Keys type with only a change that object need not copy keys from the Any type it is defined from.
Welcome to Node.js v12.16.1.
Type ".help" for more information.
> const Joi = require('@hapi/joi')
undefined
> const util = require('util')
undefined
> const object1 = Joi.object({
... a: Joi.number().min(1).max(10).integer(),
... b: Joi.any()
... });
undefined
> const object2 = Joi.object().keys({
... a: Joi.number().min(1).max(10).integer(),
... b: Joi.any()
... });
undefined
> util.format(object1) == util.format(object2)
true
> object1.validate({a: 1, b: 1})
{ value: { a: 1, b: 1 } }
> object2.validate({a: 1, b: 1})
{ value: { a: 1, b: 1 } }
> object1.validate({a: 0})
{
value: { a: 0 },
error: [Error [ValidationError]: "a" must be larger than or equal to 1] {
_original: { a: 0 },
details: [ [Object] ]
}
}
> object2.validate({a: 0})
{
value: { a: 0 },
error: [Error [ValidationError]: "a" must be larger than or equal to 1] {
_original: { a: 0 },
details: [ [Object] ]
}
}
> object1.validate({a: 1, b: 1, c:1})
{
value: { a: 1, b: 1, c: 1 },
error: [Error [ValidationError]: "c" is not allowed] {
_original: { a: 1, b: 1, c: 1 },
details: [ [Object] ]
}
}
> object2.validate({a: 1, b: 1, c:1})
{
value: { a: 1, b: 1, c: 1 },
error: [Error [ValidationError]: "c" is not allowed] {
_original: { a: 1, b: 1, c: 1 },
details: [ [Object] ]
}
}
> object1.validate({a: 1})
{ value: { a: 1 } }
> object2.validate({a: 1})
{ value: { a: 1 } }
> object1.validate({b: 1})
{ value: { b: 1 } }
> object2.validate({b: 1})
{ value: { b: 1 } }
> object1.validate({})
{ value: {} }
> object2.validate({})
{ value: {} }
Difference between the .append(schema)
and .keys(schema)
is also unclear in documentation. The .append(schema)
does not create a new copy if schema is empty, but otherwise it just returns the value from .keys(schema)
. I found no example where this would make a difference.
> util.format(Joi.object({}).keys({a:1})) == util.format(Joi.object({}).append({a:1}))
true
> util.format(Joi.object({}).unknown().keys({a:1})) == util.format(Joi.object({}).unknown().append({a:1}))
true