Keywords: Yup Validation | Phone Number Validation | Regular Expressions | JavaScript | Form Validation
Abstract: This article provides an in-depth exploration of various methods for implementing phone number validation using the Yup validation library. It begins by analyzing the limitations of using Yup.number() for numeric validation, then details the solution of matching string formats through regular expressions, including complete regex patterns and error handling mechanisms. The article also supplements with advanced validation methods using the yup-phone plugin and libphonenumber-js library, as well as best practices for server-side validation with Abstract API. Each method includes complete code examples and practical application scenario analyses, helping developers choose the most suitable validation strategy for their project needs.
In form validation, phone number validation is a common but complex requirement. Yup, as a powerful JavaScript validation library, provides multiple ways to handle phone number validation. This article systematically introduces several main implementation methods, from basic string validation to advanced semantic validation.
Limitations of Basic Numeric Validation
Many developers initially attempt to use Yup's numeric validation methods to handle phone numbers:
phone: Yup.number()
.typeError("That doesn't look like a phone number")
.positive("A phone number can't start with a minus")
.integer("A phone number can't include a decimal point")
.min(8)
.required('A phone number is required')
However, this approach has obvious flaws. When using .min(8), it validates numerical value rather than string length. This means that entering a single digit like 8 will pass validation, while phone numbers like 1000 0000 will be rejected due to containing spaces. The fundamental issue with this method is that phone numbers are essentially strings rather than numerical values, containing formatting characters such as spaces, parentheses, and hyphens.
Regular Expression String Validation
A more reasonable approach is to treat phone numbers as strings and validate their format using regular expressions:
const phoneRegExp = /^((\+[1-9]{1,4}[ \-]*)|(\([0-9]{2,3}\)[ \-]*)|([0-9]{2,4})[ \-]*)*?[0-9]{3,4}?[ \-]*[0-9]{3,4}?$/
phoneNumber: Yup.string().matches(phoneRegExp, 'Phone number is not valid')
This regular expression can handle various phone number formats:
- Optional country code prefix (starting with +)
- Optional area code (may contain parentheses)
- Allows spaces and hyphens as separators
- Validates basic numeric structure of phone numbers
Through the .matches() method, we can precisely control the format requirements of phone numbers, ensuring user input conforms to the expected pattern.
Using Dedicated Validation Plugins
For more complex validation needs, specialized Yup plugins like yup-phone can be used:
const Yup = require('yup');
require('yup-phone');
const phoneSchema = Yup.string().phone().required();
phoneSchema.isValid('9876543210'); // → true
The yup-phone plugin, based on the google-libphonenumber library, provides more accurate phone number validation:
- Supports international phone number formats
- Automatic country code detection
- Strict format validation
- Configurable validation options
libphonenumber-js Integration
Another advanced method is direct integration with the libphonenumber-js library:
import { isValidPhoneNumber } from 'libphonenumber-js';
import * as Yup from 'yup';
const phoneSchema = Yup.string().test(
'is-valid-e164',
'Phone number is not valid',
value => isValidPhoneNumber(value || '')
);
This method leverages Google's phone number validation logic, capable of handling:
- E.164 international standard format
- Country-specific phone number rules
- Number authenticity and validity checks
Conditional Validation Strategy
In multi-country applications, Yup's conditional validation can be used to dynamically adjust validation rules:
const schema = Yup.object({
country: Yup.string().required(),
phone: Yup.string().when('country', {
is: 'US',
then: Yup.string().matches(/^\+1\d{10}$/, 'US phone invalid'),
otherwise: Yup.string().test(
'intl',
'International phone invalid',
v => isValidPhoneNumber(v || '')
)
})
});
This strategy allows applying different validation rules based on the user's selected country, improving validation accuracy and user experience.
Server-Side Validation Supplement
While client-side validation is important, server-side validation is equally indispensable. Services like Abstract API can be used for supplementary validation:
import axios from 'axios';
import * as Yup from 'yup';
const phoneSchema = Yup.string()
.required('phone required')
.matches(/^\+?[1-9]\d{9,14}$/, 'bad format');
export async function validatePhone(value) {
await phoneSchema.validate(value); // fast client check
const { data } = await axios.get(
'https://phonevalidation.abstractapi.com/v1/',
{ params: { api_key: process.env.ABSTRACT_API_KEY, phone: value } }
);
if (!data.valid) throw new Error('unreachable phone');
return data; // contains carrier, region, etc.
}
This approach combines the advantages of fast client-side validation and deep server-side validation, providing the most reliable validation solution.
Best Practices Summary
When choosing a phone number validation strategy, consider the following factors:
- Project Complexity: Simple projects can use regular expressions, while complex projects should use specialized libraries
- Internationalization Needs: Multi-country applications should use libphonenumber-js or similar libraries
- Security Requirements: Critical applications should combine server-side validation
- User Experience: Provide clear error messages and real-time validation feedback
By reasonably selecting validation strategies, you can ensure the accuracy and completeness of phone number data while providing a good user experience.