Object type
Ensure the value of a field is a valid JavaScript object literal. You may define a collection of properties you want to validate within the object.
import vine from '@vinejs/vine'
const schema = vine.object({
username: vine.string(),
password: vine.string(),
})
Using the following modifiers, you may mark the field as optional
or nullable
.
See also: Working with undefined
and null
values
{
profile: vine.object({
twitter_handle: vine.string(),
github_username: vine.string(),
})
.nullable()
}
{
profile: vine.object({
twitter_handle: vine.string(),
github_username: vine.string(),
})
.optional()
}
Allowing unknown properties
The unknown properties in the data
object are ignored during the validation, and the validated output only contains the known properties.
However, you may allow unknown properties using the allowUnknownProperties
method. In this case, VineJS will validate the known properties and copy (using deepClone
) the rest of the properties to the output.
import vine from '@vinejs/vine'
const schema = vine.object({
username: vine.string(),
password: vine.string(),
})
const data = {
username: 'virk',
password: 'secret',
rememberMe: true,
trackLogin: true,
}
const validate = vine.compile(schema)
const output = await validate(data)
/**
{
username: 'virk',
password: 'secret'
}
*/
import vine from '@vinejs/vine'
const schema = vine.object({
username: vine.string(),
password: vine.string(),
})
.allowUnknownProperties()
const data = {
username: 'virk',
password: 'secret',
rememberMe: true,
trackLogin: true,
}
const validate = vine.compile(schema)
const output = await validate(data)
/**
{
username: 'virk',
password: 'secret',
rememberMe: true,
trackLogin: true,
}
*/
You can use the allowUnknownProperties
with nested objects as well.
const schema = vine.object({
profile: vine
.object({
twitter_handle: vine.string(),
github_username: vine.string(),
})
.allowUnknownProperties()
})
Object groups
Object groups allow you to validate additional properties based on a condition. Each group can have multiple conditions, and each condition has an associated schema.
In the following example, we validate a form to issue a monument ticket to a visitor. The visitor may optionally hire a guide, and if they do, we must validate the guide id, and the amount the guide will charge.
Before creating the validation schema, let's visualize the expected type we want for this schema.
/**
* Just for visualization purposes. Not required by VineJS
*/
type VisitorDetails = {
name: string
group_size: number
phone_number: string
} & ({
is_hiring_guide: true,
guide_id: string,
amount: number,
} | {
is_hiring_guide: false,
})
Instead of marking additional fields like guide_id
or amount
optional, we create a union of types. Unions provide great type safety when you perform type narrowing in TypeScript.
Let's reproduce the VisitorDetails
type using the VineJS schema API.
import vine from '@vinejs/vine'
const guideSchema = vine.group([
vine.group.if(
(data) => vine.helpers.isTrue(data.is_hiring_guide),
{
is_hiring_guide: vine.literal(true),
guide_id: vine.string(),
amount: vine.number(),
}
),
vine.group.else({
is_hiring_guide: vine.literal(false),
}),
])
const schema = vine.object({
name: vine.string(),
group_size: vine.number(),
phone_number: vine.string()
})
.merge(guideSchema)
The vine.group
method accepts an array of conditions and the schema to use if the condition is true
at runtime. In our example, we have the following two conditions.
- We will use the first schema if the
data
hasis_hiring_guide = true
. - Otherwise, we will use the second schema inside the group array.
Finally, we merge the group with the object using the object.merge
method. You may call the merge
method multiple times, and each call will result in an intersection type of unions.
group.if
The vine.group.if
method accepts a callback as the first argument and the schema to use as the second argument. The schema will be used for the validation if the callback returns true
. Otherwise, the group will move to the next condition.
vine.group.if((data, field) => {
return true
}, {
})
group.else
The vine.group.else
method defines a fallback schema when none of the if
conditions match. The else
condition must last in the vine.group
array.
vine.group.else({
// fallback schema
})
group.otherwise
If you do not have a fallback schema, you must define an otherwise
callback to report an error when none of the conditions are matched. For example:
vine.group([
vine.group.if((data) => 'username' in data, {
username: vine.string()
}),
vine.group.if((data) => 'email' in data, {
email: vine.string().email()
})
])
.otherwise((field) => {
field.report(
'You must provide username or email to login',
'email_or_username',
field
)
})
Merging properties
You may merge properties from an existing object to a new object using the JavaScript spread syntax. In the following example, the author.getProperties()
method returns a cloned copy of properties from the author
schema.
const author = vine.object({
name: vine.string(),
email: vine.string().email()
})
const commentSchema = vine
.object({
...author.getProperties(),
body: vine.string(),
})
/**
{
name: string,
email: string,
body: string,
}
*/
Defining error message
You may define the custom error message using the object
rule name.
const messages = {
object: 'The {{ field }} field must be an object'
}
vine.messagesProvider = new SimpleMessagesProvider(messages)