Skip to content

Phone number validation in JavaScript

isValid is the verdict. isPossibleWithReason checks the calling code and the length and never reads the digits, which is why a number nobody was assigned can still pass. getValidationError names the exact fault, with the length or the prefix that fixes it where one exists.

An unfinished number comes back TOO_SHORT. A number whose digits belong to no assigned range still comes back IS_POSSIBLE, because the check never reads them.

import { parsePhoneNumber } from '@telixon/core';
function reason(input: string) {
return parsePhoneNumber(input, { defaultRegion: 'US' }).isPossibleWithReason();
}
reason('+1 415'); // 'TOO_SHORT'
reason('+999 123'); // 'INVALID_CALLING_CODE'
reason('+1 21255512345678'); // 'TOO_LONG'
reason('+1 999 555 0132'); // 'IS_POSSIBLE', while isValid() is false

The six reason codes are under PossibilityResult.

getValidationError returns null when nothing needs correcting. A valid number typed without its trunk prefix still gets NATIONAL_PREFIX_MISSING, which is why this guide gates on isValid first. Otherwise it returns one of nine kinds. Five of them carry the length or the prefix behind the fault:

import { parsePhoneNumber, type ValidationError } from '@telixon/core';
function describe(error: ValidationError): string {
switch (error.kind) {
case 'EMPTY':
return 'Enter a phone number.';
case 'INVALID_CALLING_CODE':
return 'No country uses this calling code.';
case 'TOO_SHORT':
return `Too short. Use at least ${error.minLength} digits.`;
case 'TOO_LONG':
return `Too long. Use at most ${error.maxLength} digits.`;
case 'INVALID_LENGTH':
return `Wrong length. Valid lengths are ${error.possibleLengths.join(', ')}.`;
case 'POSSIBLE_LOCAL_ONLY':
return 'Add the area code.';
case 'PATTERN_MISMATCH':
return 'This number does not exist in this region.';
case 'NATIONAL_PREFIX_MISSING':
return `Start the number with ${error.expectedPrefix}.`;
case 'NATIONAL_PREFIX_PRESENT':
return `Remove the leading ${error.prefix}.`;
}
}
const number = parsePhoneNumber('+1 415');
if (!number.isValid()) {
describe(number.getValidationError()!); // 'Too short. Use at least 10 digits.'
}

The error answers for the value as it stands, which means a half-typed number reports TOO_SHORT the same way a finished wrong one does.

To restrict validity to a single region at parse time, use strict.

formatE164 produces the canonical string. It parses back with no options:

parsePhoneNumber('(415) 555-0132', { defaultRegion: 'US' }).formatE164(); // '+14155550132'
parsePhoneNumber('+14155550132').isValid(); // true