A regex for “valid phone number” is a trap. International phone numbering isn’t regular: number length, valid area codes, and mobile-vs-landline prefixes differ per country and change over time as ranges get reassigned. A regex that’s correct today starts silently misclassifying numbers months later, and you won’t notice until a support ticket comes in.
The actual fix is using the numbering-plan data Google publishes and maintains for Android/Chrome: libphonenumber, or its much smaller JS port libphonenumber-js.
import { parsePhoneNumberFromString } from "libphonenumber-js";
const phone = parsePhoneNumberFromString("+49 30 1234567");
phone?.isValid(); // true - checks length + pattern for that country
phone?.country; // "DE"
phone?.getType(); // "FIXED_LINE" | "MOBILE" | undefined (not always determinable)
phone?.formatInternational(); // "+49 30 1234567", normalized
Enter fullscreen mode Exit fullscreen mode
Two things regex can’t give you that this does for free:
- Country-aware validity. “Valid length” isn’t one number — it varies by country and sometimes by number type within a country. The library knows the real ranges, and gets updated when they change.
-
Normalization. Users type phone numbers a dozen different ways (spaces, dashes, parens, with or without country code).
formatInternational()gives you one canonical form to store and compare against, instead of writing your own normalization pass.
One gotcha: without a country hint, a local-format number is ambiguous. 030 1234567 is valid in Germany and might also just be a truncated something-else from another country. If your form is scoped to one country, pass it as the default country rather than relying purely on a + prefix being present.
If your backend isn’t JS (or you don’t want the dependency in a small service), I wrapped libphonenumber-js as a hosted endpoint on Validate — same validation logic, plain JSON in and out.
답글 남기기