Skip to main content

Present Rules

Conditional present validation rules that make fields present (but not necessarily required) based on other field values or presence.


All Methods


Based on Field Presence

presentWith()

Field must be present if another field exists.

Signature:

presentWith(field: string, errorMessage?: string): this

Example:

v.string().presentWith("email")

// Input: { email: "user@example.com", name: "John" }
// Output: "John" ✅

// Input: { email: "user@example.com", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { name: "John" }
// Output: "John" ✅ (email not present, so name not required to be present)

Common Use:

// Contact form - name must be present if email provided
v.object({
email: v.string().optional().email(),
name: v.string().presentWith("email").max(100)
});

presentWithout()

Field must be present if another field is missing.

Signature:

presentWithout(field: string, errorMessage?: string): this

Example:

v.string().presentWithout("email")

// Input: { email: "user@example.com", phone: undefined }
// Output: undefined ✅ (email present, so phone not required to be present)

// Input: { phone: "123-456-7890" }
// Output: "123-456-7890" ✅ (email not present, so phone must be present)

// Input: { email: undefined, phone: undefined }
// Output: Error: "The :input field must be present" ❌

Common Use:

// Contact form - phone must be present if no email
v.object({
email: v.string().optional().email(),
phone: v.string().presentWithout("email").phone()
});

Based on Field Value

presentIf()

Field must be present if another field equals a specific value.

Signature:

presentIf(field: string, value: any, errorMessage?: string): this

Example:

v.string().presentIf("type", "admin")

// Input: { type: "admin", role: "super-admin" }
// Output: "super-admin" ✅

// Input: { type: "admin", role: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { type: "user", role: undefined }
// Output: undefined ✅ (type not "admin", so role not required to be present)

Common Use:

// User registration - role must be present for admin
v.object({
type: v.string().required().oneOf(["admin", "user"]),
role: v.string().presentIf("type", "admin").max(50)
});

presentUnless()

Field must be present unless another field equals a specific value.

Signature:

presentUnless(field: string, value: any, errorMessage?: string): this

Example:

v.string().presentUnless("type", "guest")

// Input: { type: "user", name: "John" }
// Output: "John" ✅

// Input: { type: "user", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { type: "guest", name: undefined }
// Output: undefined ✅ (type is "guest", so name not required to be present)

Common Use:

// User registration - name must be present unless guest
v.object({
type: v.string().required().oneOf(["admin", "user", "guest"]),
name: v.string().presentUnless("type", "guest").max(100)
});

Based on Field Empty State

presentIfEmpty()

Field must be present if another field is empty.

Signature:

presentIfEmpty(field: string, errorMessage?: string): this

Example:

v.string().presentIfEmpty("email")

// Input: { email: "", phone: "123-456-7890" }
// Output: "123-456-7890" ✅

// Input: { email: "", phone: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { email: "user@example.com", phone: undefined }
// Output: undefined ✅ (email not empty, so phone not required to be present)

Common Use:

// Contact form - phone must be present if email empty
v.object({
email: v.string().optional().email(),
phone: v.string().presentIfEmpty("email").phone()
});

presentIfNotEmpty()

Field must be present if another field is not empty.

Signature:

presentIfNotEmpty(field: string, errorMessage?: string): this

Example:

v.string().presentIfNotEmpty("email")

// Input: { email: "user@example.com", name: "John" }
// Output: "John" ✅

// Input: { email: "user@example.com", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { email: "", name: undefined }
// Output: undefined ✅ (email empty, so name not required to be present)

Common Use:

// Profile form - name must be present if email provided
v.object({
email: v.string().optional().email(),
name: v.string().presentIfNotEmpty("email").max(100)
});

Based on Field Value Arrays

presentIfIn()

Field must be present if another field's value is in the given array.

Signature:

presentIfIn(field: string, values: any[], errorMessage?: string): this

Example:

v.string().presentIfIn("type", ["admin", "moderator"])

// Input: { type: "admin", role: "super-admin" }
// Output: "super-admin" ✅

// Input: { type: "admin", role: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { type: "user", role: undefined }
// Output: undefined ✅ (type not in ["admin", "moderator"])

Common Use:

// User roles - role must be present for admin/moderator
v.object({
type: v.string().required().oneOf(["admin", "moderator", "user"]),
role: v.string().presentIfIn("type", ["admin", "moderator"]).max(50)
});

presentIfNotIn()

Field must be present if another field's value is NOT in the given array.

Signature:

presentIfNotIn(field: string, values: any[], errorMessage?: string): this

Example:

v.string().presentIfNotIn("type", ["guest", "anonymous"])

// Input: { type: "user", name: "John" }
// Output: "John" ✅

// Input: { type: "user", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { type: "guest", name: undefined }
// Output: undefined ✅ (type in ["guest", "anonymous"])

Common Use:

// User registration - name must be present for registered users
v.object({
type: v.string().required().oneOf(["admin", "user", "guest", "anonymous"]),
name: v.string().presentIfNotIn("type", ["guest", "anonymous"]).max(100)
});

Multiple Field Rules

presentWithAll()

Field must be present if all specified fields exist.

Signature:

presentWithAll(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithAll(["email", "phone"])

// Input: { email: "user@example.com", phone: "123-456-7890", name: "John" }
// Output: "John" ✅

// Input: { email: "user@example.com", phone: "123-456-7890", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { email: "user@example.com", name: "John" }
// Output: "John" ✅ (phone not present, so name not required to be present)

Common Use:

// Complete profile - name must be present if both email and phone provided
v.object({
email: v.string().optional().email(),
phone: v.string().optional().phone(),
name: v.string().presentWithAll(["email", "phone"]).max(100)
});

presentWithAny()

Field must be present if any of the specified fields exists.

Signature:

presentWithAny(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithAny(["email", "phone"])

// Input: { email: "user@example.com", name: "John" }
// Output: "John" ✅

// Input: { email: "user@example.com", name: undefined }
// Output: Error: "The :input field must be present" ❌

// Input: { name: "John" }
// Output: "John" ✅ (neither email nor phone present)

Common Use:

// Contact form - name must be present if any contact method provided
v.object({
email: v.string().optional().email(),
phone: v.string().optional().phone(),
name: v.string().presentWithAny(["email", "phone"]).max(100)
});

Sibling Field Rules

presentWithSibling()

Field must be present if another sibling field exists (for nested objects).

Signature:

presentWithSibling(field: string, errorMessage?: string): this

Example:

v.string().presentWithSibling("email")

// Input: { profile: { email: "user@example.com", name: "John" } }
// Output: "John" ✅

// Input: { profile: { email: "user@example.com", name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentWithoutSibling()

Field must be present if another sibling field is missing (for nested objects).

Signature:

presentWithoutSibling(field: string, errorMessage?: string): this

Example:

v.string().presentWithoutSibling("email")

// Input: { profile: { email: "user@example.com", phone: undefined } }
// Output: undefined ✅ (email present, so phone not required to be present)

// Input: { profile: { phone: "123-456-7890" } }
// Output: "123-456-7890" ✅ (email not present, so phone must be present)

presentIfSibling()

Field must be present if another sibling field equals a specific value (for nested objects).

Signature:

presentIfSibling(field: string, value: any, errorMessage?: string): this

Example:

v.string().presentIfSibling("type", "admin")

// Input: { user: { type: "admin", role: "super-admin" } }
// Output: "super-admin" ✅

// Input: { user: { type: "admin", role: undefined } }
// Output: Error: "The :input field must be present" ❌

presentUnlessSibling()

Field must be present unless another sibling field equals a specific value (for nested objects).

Signature:

presentUnlessSibling(field: string, value: any, errorMessage?: string): this

Example:

v.string().presentUnlessSibling("type", "guest")

// Input: { user: { type: "user", name: "John" } }
// Output: "John" ✅

// Input: { user: { type: "guest", name: undefined } }
// Output: undefined ✅ (type is "guest", so name not required to be present)

presentIfEmptySibling()

Field must be present if another sibling field is empty (for nested objects).

Signature:

presentIfEmptySibling(field: string, errorMessage?: string): this

Example:

v.string().presentIfEmptySibling("email")

// Input: { profile: { email: "", phone: "123-456-7890" } }
// Output: "123-456-7890" ✅

// Input: { profile: { email: "", phone: undefined } }
// Output: Error: "The :input field must be present" ❌

presentIfNotEmptySibling()

Field must be present if another sibling field is not empty (for nested objects).

Signature:

presentIfNotEmptySibling(field: string, errorMessage?: string): this

Example:

v.string().presentIfNotEmptySibling("email")

// Input: { profile: { email: "user@example.com", name: "John" } }
// Output: "John" ✅

// Input: { profile: { email: "user@example.com", name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentIfInSibling()

Field must be present if another sibling field's value is in the given array (for nested objects).

Signature:

presentIfInSibling(field: string, values: any[], errorMessage?: string): this

Example:

v.string().presentIfInSibling("type", ["admin", "moderator"])

// Input: { user: { type: "admin", role: "super-admin" } }
// Output: "super-admin" ✅

// Input: { user: { type: "admin", role: undefined } }
// Output: Error: "The :input field must be present" ❌

presentIfNotInSibling()

Field must be present if another sibling field's value is NOT in the given array (for nested objects).

Signature:

presentIfNotInSibling(field: string, values: any[], errorMessage?: string): this

Example:

v.string().presentIfNotInSibling("type", ["guest", "anonymous"])

// Input: { user: { type: "user", name: "John" } }
// Output: "John" ✅

// Input: { user: { type: "user", name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentWithAllSiblings()

Field must be present if all specified sibling fields exist (for nested objects).

Signature:

presentWithAllSiblings(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithAllSiblings(["email", "phone"])

// Input: { profile: { email: "user@example.com", phone: "123-456-7890", name: "John" } }
// Output: "John" ✅

// Input: { profile: { email: "user@example.com", phone: "123-456-7890", name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentWithAnySiblings()

Field must be present if any of the specified sibling fields exists (for nested objects).

Signature:

presentWithAnySiblings(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithAnySiblings(["email", "phone"])

// Input: { profile: { email: "user@example.com", name: "John" } }
// Output: "John" ✅

// Input: { profile: { email: "user@example.com", name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentWithoutAllSiblings()

Field must be present if all specified sibling fields are missing (for nested objects).

Signature:

presentWithoutAllSiblings(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithoutAllSiblings(["email", "phone"])

// Input: { profile: { name: "John" } }
// Output: "John" ✅

// Input: { profile: { name: undefined } }
// Output: Error: "The :input field must be present" ❌

presentWithoutAnySiblings()

Field must be present if any of the specified sibling fields is missing (for nested objects).

Signature:

presentWithoutAnySiblings(fields: string[], errorMessage?: string): this

Example:

v.string().presentWithoutAnySiblings(["email", "phone"])

// Input: { profile: { email: "user@example.com", name: "John" } }
// Output: "John" ✅ (phone is missing, so name must be present)

// Input: { profile: { email: "user@example.com", name: undefined } }
// Output: Error: "The :input field must be present" ❌

Chaining Examples

// Complex conditional validation
v.string()
.presentIf("type", "admin")
.presentIfNotEmpty("email")
.presentWithAny(["phone", "address"])
.max(100)

Real-World Examples

User Registration Form

const registrationSchema = v.object({
type: v.string().required().oneOf(["admin", "user", "guest"]),
email: v.string().optional().email(),
phone: v.string().optional().phone(),
name: v.string().presentUnless("type", "guest"),
role: v.string().presentIf("type", "admin"),
address: v.string().presentWithAll(["email", "phone"])
});

Contact Form

const contactSchema = v.object({
email: v.string().optional().email(),
phone: v.string().optional().phone(),
name: v.string().presentWithAny(["email", "phone"]),
message: v.string().required().min(10)
});

See Also