Avatar of ChowSinWon

ChowSinWon's solution

to Phone Number in the TypeScript Track

Published at Oct 05 2019 · 0 comments
Instructions
Test suite
Solution

Clean up user-entered phone numbers so that they can be sent SMS messages.

The North American Numbering Plan (NANP) is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: 1.

NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as area code, followed by a seven-digit local number. The first three digits of the local number represent the exchange code, followed by the unique four-digit number which is the subscriber number.

The format is usually represented as

(NXX)-NXX-XXXX

where N is any digit from 2 through 9 and X is any digit from 0 through 9.

Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code (1) if present.

For example, the inputs

  • +1 (613)-995-0253
  • 613-995-0253
  • 1 613 995 0253
  • 613.995.0253

should all produce the output

6139950253

Note: As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code.

Setup

Go through the setup instructions for TypeScript to install the necessary dependencies:

https://exercism.io/tracks/typescript/installation

Requirements

Install assignment dependencies:

$ yarn install

Making the test suite pass

Execute the tests with:

$ yarn test

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by changing xit to it.

Source

Event Manager by JumpstartLab http://tutorials.jumpstartlab.com/projects/eventmanager.html

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

phone-number.test.ts

import PhoneNumber from './phone-number'

describe('PhoneNumber()', () => {

  it('cleans the number', () => {
    const phone = new PhoneNumber('(223) 456-7890')
    expect(phone.number()).toEqual('2234567890')
  })

  xit('cleans numbers with dots', () => {
    const phone = new PhoneNumber('223.456.7890')
    expect(phone.number()).toEqual('2234567890')
  })

  xit('cleans numbers with multiple spaces', () => {
    const phone = new PhoneNumber('223 456   7890   ')
    expect(phone.number()).toEqual('2234567890')
  })

  xit('invalid when 9 digits', () => {
    const phone = new PhoneNumber('123456789')
    expect(phone.number()).toEqual(undefined)
  })

  xit('invalid when 11 digits', () => {
    const phone = new PhoneNumber('21234567890')
    expect(phone.number()).toEqual(undefined)
  })

  xit('valid when 11 digits and starting with 1', () => {
    const phone = new PhoneNumber('11234567890')
    expect(phone.number()).toEqual('1234567890')
  })

  xit('invalid when 12 digits', () => {
    const phone = new PhoneNumber('321234567890')
    expect(phone.number()).toEqual(undefined)
  })

  xit('invalid with letters', () => {
    const phone = new PhoneNumber('123-abc-7890')
    expect(phone.number()).toEqual(undefined)
  })

  xit('invalid with punctuations', () => {
    const phone = new PhoneNumber('123-@:!-7890')
    expect(phone.number()).toEqual(undefined)
  })

  xit('invalid with right number of digits but letters mixed in', () => {
    const phone = new PhoneNumber('1a2b3c4d5e6f7g8h9i0j')
    expect(phone.number()).toEqual(undefined)
  })

})

phone-number.ts

class PhoneNumber {
  constructor(private input: string) {}

  public number(): string|undefined {
    const matches = [...this.input]
      .filter(char => char.match(/^\w$/) !== null)
      .join('')
      .match(/^1?([2-9]\d{2}[2-9]\d{6})$/);

    return matches === null ? undefined : matches[1];
  }
}

export default PhoneNumber;

phone-number.test.ts

import PhoneNumber from './phone-number'

describe('PhoneNumber()', () => {

  it('cleans the number', () => {
    const phone = new PhoneNumber('(223) 456-7890')
    expect(phone.number()).toEqual('2234567890')
  })

  it('cleans numbers with dots', () => {
    const phone = new PhoneNumber('223.456.7890')
    expect(phone.number()).toEqual('2234567890')
  })

  it('cleans numbers with multiple spaces', () => {
    const phone = new PhoneNumber('223 456   7890   ')
    expect(phone.number()).toEqual('2234567890')
  })

  it('invalid when 9 digits', () => {
    const phone = new PhoneNumber('123456789')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid when 11 digits', () => {
    const phone = new PhoneNumber('21234567890')
    expect(phone.number()).toEqual(undefined)
  })

  it('valid when 11 digits and starting with 1', () => {
    const phone = new PhoneNumber('16234567890')
    expect(phone.number()).toEqual('6234567890')
  })

  it('invalid when 12 digits', () => {
    const phone = new PhoneNumber('321234567890')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid with letters', () => {
    const phone = new PhoneNumber('623-abc-7890')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid with punctuations', () => {
    const phone = new PhoneNumber('623-@:!-7890')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid with right number of digits but letters mixed in', () => {
    const phone = new PhoneNumber('6a2b3c4d5e6f7g8h9i0j')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid area code', () => {
    const phone = new PhoneNumber('(123) 456-7890')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid exchange code', () => {
    const phone = new PhoneNumber('(223) 056-7890')
    expect(phone.number()).toEqual(undefined)
  })

  it('invalid with non-NANP country code', () => {
    const phone = new PhoneNumber('+2 (223) 456-7890')
    expect(phone.number()).toEqual(undefined)
  })
})

Community comments

Find this solution interesting? Ask the author a question to learn more.

ChowSinWon's Reflection

This is the first time after 43 exercises in this track that I felt I needed to change the test file.
The instructions clearly state: "this exercise only deals with telephone numbers used in NANP-countries" and even delivers the format: "(NXX)-NXX-XXXX where N is any digit from 2 through 9 and X is any digit from 0 through 9".
And still there are tests where the phone number (without country code) starts with 1 - which is per definition wrong and thus should result in undefined! I changed the first digit to a 6 so the test could still test what it inteded to do.
Furthermore I added three new tests that explicitly check for invalid area and exchange codes as defined in the simple format and non-NANP country code.

With those changes and additional criteria (not only cleaning up and removing country code 1 but also align with the format) I found it a lot easier to check the phone numbers, because now I only had to filter out all non-word-characters and then see if the resulting number fits into the (digit-only) format NXXNXXXXXX with an optional leading 1 as area code and finally return that number (without area code).