Skip to content

parsePhoneNumber

parsePhoneNumber parses a string into a PhoneNumber. It is the batch entry into the shared resolve layer: parsePhoneNumber and the input controller are the same shared resolve layer, queried in batch versus per keystroke, so one call is one walk of the automaton over the whole input.

import { parsePhoneNumber } from '@telixon/core';
import type { ParsePhoneNumberOptions } from '@telixon/core';
export function parsePhoneNumber(input: string, options: ParsePhoneNumberOptions = {}): PhoneNumber;
export interface ParsePhoneNumberOptions {
// Assumed region for input without a leading '+'.
defaultRegion?: RegionCode;
// Restrict validity (`isValid`/`getNumberType`) to `defaultRegion` (libphonenumber isValidNumberForRegion);
// `getRegion`, `isPossible`, and `format*` ignore it. No effect without `defaultRegion`; off by default.
strict?: boolean;
}
Parameter Type Default Meaning
input string required Raw text to parse. The walk keeps digits and one leading +; punctuation, spaces, and letters are discarded.
options.defaultRegion RegionCode undefined Assumed region for input without a leading +. Valid codes are the entries of REGION_CODES.
options.strict boolean false Restricts validity (isValid, getNumberType) to defaultRegion, matching Google libphonenumber’s isValidNumberForRegion. getRegion, isPossible, and format* ignore it. No effect without defaultRegion.

Always a PhoneNumber. Bad input never throws: validity is an accepting state, and every ValidationError variant is a named way of not being in one, so an unparseable string comes back as a PhoneNumber whose getValidationError() is non-null.

const number = parsePhoneNumber('garbage');
number.isValid(); // false
number.getValidationError(); // { kind: 'EMPTY' }
number.formatE164(); // null

The error is EMPTY because letters are not digits: nothing survives the walk.

parsePhoneNumber throws in exactly one case: EngineNotReadyError, when it is called before the engine is initialized with ensureEngineReady.

parsePhoneNumber('+1 415 555 0132');
// EngineNotReadyError: Telixon engine is not initialized.

Everything else, including empty strings and non-numeric input, is reported on the returned PhoneNumber.

If the input starts with + (leading whitespace is allowed before it), the calling code is read off the front of the walk and the region is inferred from the digits. defaultRegion does not participate in inference:

parsePhoneNumber('+44 20 7946 0958', { defaultRegion: 'US' }).getRegion(); // 'GB'

Without a leading +, defaultRegion interprets the digits in national notation, including that region’s national prefix rules:

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

With neither a + nor a defaultRegion, the digits are still walked from the automaton root, as an international number written without its plus:

parsePhoneNumber('14155550132').getRegion(); // 'US'

This is the right reading for stored E.164 digits, but not for user-entered national input; see the pitfall under Examples.

With strict: true, isValid and getNumberType accept only numbers valid for defaultRegion, matching Google libphonenumber’s isValidNumberForRegion. getRegion, isPossible, and the format* methods ignore the flag, and it has no effect without defaultRegion; see Strict mode.

Digits drive one deterministic automaton compiled from Google’s metadata; the walk strips punctuation, spaces, and any other non-digit characters as it goes, so common human formattings resolve identically:

parsePhoneNumber('+1 (415) 555-0132').formatE164(); // '+14155550132'
parsePhoneNumber('+1 415 555 0132').formatE164(); // '+14155550132'
import { ensureEngineReady, parsePhoneNumber } from '@telixon/core';
await ensureEngineReady();
const number = parsePhoneNumber('+1 415 555 0132');
number.isValid(); // true
number.getRegion(); // 'US'
number.getNumberType(); // 'FIXED_LINE_OR_MOBILE'
number.formatE164(); // '+14155550132'
number.formatNational(); // '(415) 555-0132'
number.formatInternational(); // '+1 415-555-0132'
const number = parsePhoneNumber('(415) 555-0132', { defaultRegion: 'US' });
number.isValid(); // true
number.formatE164(); // '+14155550132'
const number = parsePhoneNumber('415 555', { defaultRegion: 'US' });
number.isValid(); // false
number.getValidationError(); // { kind: 'TOO_SHORT', minLength: 10 }
number.formatE164(); // null

The full set of variants and their payloads is on ValidationError.

const strict = parsePhoneNumber('+1 212 555 0198', { defaultRegion: 'CA', strict: true });
strict.isValid(); // false
strict.getNumberType(); // 'UNKNOWN'
strict.getRegion(); // 'US'
strict.formatE164(); // '+12125550198'
const loose = parsePhoneNumber('+1 212 555 0198', { defaultRegion: 'CA' });
loose.isValid(); // true

The number is a real US number, so getRegion() and formatE164() still report it; only validity and number type are restricted to CA.

Pitfall: national input without defaultRegion

Section titled “Pitfall: national input without defaultRegion”
const bare = parsePhoneNumber('415 555 0132');
bare.getCallingCode(); // '41'
bare.getValidationError(); // { kind: 'TOO_SHORT', minLength: 9 }

Without a + and without a defaultRegion, the leading digits are consumed as a calling code, here 41. Pass defaultRegion whenever the input is user-entered national notation.