Phone Number Formatter JavaScript

Day 4 of 365 Days of Coding challenge!

Disclaimer: there are MANY ways to solve this problem this is an answers that I would see or use in a coding interview and would accept as a proper answer

TLDR: Solution is at the bottom of the post

The Problem

Write a function that accepts a string of numbers or a number and converts it to a US phone number format.

Examples:

     phoneFormat(2359654144) //'235-965-4144'
     phoneFormat('2359654144') //'235-965-4144'
     phoneFormat([2359654144]) //'235-965-4144'
     phoneFormat(1234) //error: was not supplied enough numbers please pass a 10 digit number
     phoneFormat(23596541445) //error: was supplied too many numbers please pass a 10 digit number
     phoneFormat('235$96541445') //error: input must be a number
     phoneFormat([213]) //error: was not supplied enough numbers please pass a 10 digit number
     phoneFormat(null) //error: input must be a number was sent null

Solution

Lets write out what we are going to need to do

  • create a function that accepts an input

    • check if the string is a number (doesn’t include characters or letters) and not null or undefined

    • check if the input is a string if not convert it into a string

    • check if the input length is 10 (us number is 10 digits)

      • if it is

        • format it to xxx-xxx-xxxx

      • if not check if it is less than 10

        • return error was not supplied enough numbers please pass a 10 digit number

        • if not check if length is greater than 10

          • return was supplied too many numbers please pass a 10 digit number

          • if not send something went wrong error for a catch all just in case

If you are unfamiliar with if statements please check out this MDN page before going any further.

First we need to create our function

const phoneFormat = (input) => {
    //check if the string is a number (doesn’t include characters or letters) and not null or undefined
    //check if the input is a string if not convert it into a string
    //check if the input length is 10 (us number is 10 digits)
        //if it is
            //format it to xxx-xxx-xxxx
            //if not check if it is less than 10
                //return error was not supplied enough numbers please pass a 10 digit number
                //if not check if length is greater than 10
                    //return was supplied too many numbers please pass a 10 digit number
                    //if not send something went wrong error for a catch all just in case
}

We need to check if the string is a number (doesn’t include characters or letters) and not null or undefined. To do this we are going to use isNaN(). NaN stands for not a number. the built in JavaScript function does count strings of only numbers as numbers. If you are not familiar with this please check out this MDN page before continuing.

We are also going to use a template literal to make our error a little more helpful if you are unfamiliar with template literals please read this MDN page.

const phoneFormat = (input) => {
    if(!input || isNaN(input)) return `input must be a number was sent ${input}`
    //check if the input is a string if not convert it into a string
    //check if the input length is 10 (us number is 10 digits)
        //if it is
            //format it to xxx-xxx-xxxx
            //if not check if it is less than 10
                //return error was not supplied enough numbers please pass a 10 digit number
                //if not check if length is greater than 10
                    //return was supplied too many numbers please pass a 10 digit number
                    //if not send something went wrong error for a catch all just in case
}

If our input is not a string we need to make it a string so we can do our transform. If you are not familiar with .toString() please check out this MDN page before continuing

const phoneFormat = (input) => {
    if(!input || isNaN(input)) return `input must be a number was sent ${input}`
    if(typeof(input) !== 'string') input = input.toString()
    //check if the input length is 10 (us number is 10 digits)
        //if it is
            //format it to xxx-xxx-xxxx
            //if not check if it is less than 10
                //return error was not supplied enough numbers please pass a 10 digit number
                //if not check if length is greater than 10
                    //return was supplied too many numbers please pass a 10 digit number
                    //if not send something went wrong error for a catch all just in case
}

Since US phone numbers are made up of 10 digits we need to check if our input is 10 digits

const phoneFormat = (input) => {
    if(!input || isNaN(input)) return `input must be a number was sent ${input}`
    if(typeof(input) !== 'string') input = input.toString()
    if(input.length === 10){
        //if it is
            //format it to xxx-xxx-xxxx
            //if not check if it is less than 10
                //return error was not supplied enough numbers please pass a 10 digit number
                //if not check if length is greater than 10
                    //return was supplied too many numbers please pass a 10 digit number
                    //if not send something went wrong error for a catch all just in case
    }
}

If the input is 10 digits we need to format it into the phone number. If you are not familiar with .replace() please check out this MDN page. If you are not familiar with regex or would like to better understand it please check out this page. It is a great tool for testing and learning regex.

const phoneFormat = (input) => {
  if(!input || isNaN(input)) return `input must be a number was sent ${input}`
  if(typeof(input) !== 'string') input = input.toString()
  if(input.length === 10){
    return input.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
  } 
  //if not check if it is less than 10
    //return error was not supplied enough numbers please pass a 10 digit number
    //if not check if length is greater than 10
        //return was supplied too many numbers please pass a 10 digit number
        //if not send something went wrong error for a catch all just in case
}

You will notice that I formatted my string with dashes between each section (“$1-$2-$3“) if you would rather have parenthesis on the first 3 digits instead you just need to make your string (“($1)$2-$3“) instead.

Going back to our if else statement, we are going to check if the input is less than 10. If you didn’t want your errors to be specific to the length you could have a simple if else statement that was if the length was 10 format otherwise return a message about it being an invalid input. However, I wanted to make my error messages more specific so first I am going to check if the input is less than 10 and if it is return a message asking the user to supply a 10 digit number. We could so a template literal here and let them know what they did supply but I decided letting them know they didn’t supply enough numbers was enough. If you wanted to send them what they did supply you can reference the message sent in our isNaN check.

const phoneFormat = (input) => {
  if(!input || isNaN(input)) return `input must be a number was sent ${input}`
  if(typeof(input) !== 'string') input = input.toString()
  if(input.length === 10){
    return input.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
  } else if(input.length < 10){
     return 'was not supplied enough numbers please pass a 10 digit number'
  }
    //return error was not supplied enough numbers please pass a 10 digit number
    //if not check if length is greater than 10
        //return was supplied too many numbers please pass a 10 digit number
        //if not send something went wrong error for a catch all just in case
}

If the input isn’t less than 10 we are going to check if the input is greater than 10. Some people may just put an else here and return the message for is greater than 10. This is okay however, in other instances I have seen thing other than the logic checks be wrong and then you are sending the wrong error back. For instance, if something was wrong other than the length of the string that the other logic didn’t catch we would get a message saying 'was supplied too many numbers please pass a 10 digit number' when in fact that wasn’t the issue. For this simple example that is probably fine as I can’t think of much that would be wrong that we don’t have logic for but its always good to have a catch all error just in case so I am adding a specific check for greater than 10.

const phoneFormat = (input) => {
  if(!input || isNaN(input)) return `input must be a number was sent ${input}`
  if(typeof(input) !== 'string') input = input.toString()
  if(input.length === 10){
    return input.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
  } else if(input.length < 10) {
    return 'was not supplied enough numbers please pass a 10 digit number'
  } else if(input.length > 10) {
    return 'was supplied too many numbers please pass a 10 digit number'
  }
  //if not send something went wrong error for a catch all just in case
}

Now all we need is our catch all error and we are all good!

const phoneFormat = (input) => {
  if(!input || isNaN(input)) return `input must be a number was sent ${input}`
  if(typeof(input) !== 'string') input = input.toString()
  if(input.length === 10){
    return input.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
  } else if(input.length < 10) {
    return 'was not supplied enough numbers please pass a 10 digit number'
  } else if(input.length > 10) {
    return 'was supplied too many numbers please pass a 10 digit number'
  }else{
    return 'something went wrong'
  }
}

Please leave your solutions that you came up with in the comments section. If you have any challenge you would like to see done also leave that in the comments below you may see it come up! If you would like to get the challenge emailed to you every day in morning and a notification when the solution is posted subscribe below

Previous
Previous

Day 5 Challenge

Next
Next

Day 4 Challenge