Start learning free

LESSON 135 OF 675 · DICTIONARIES - CHALLENGES

Add a Contact in TypeScript: Checking a Key with in

Practice Read the full explanation

You get a phone book phoneBook, a dictionary from names to phone numbers. You also get a name and a phone number.

Add name with its number to the phone book, and return the phone book.

Only add name when it isn't in the phone book yet. A name that is already there keeps its old number. The order of the entries doesn't matter.

 

Example 1:

Input: phoneBook = {"Ana": "555-0142", "Ben": "555-0199"}, name = "Cara", number = "555-0123"
Output: {"Ana": "555-0142", "Ben": "555-0199", "Cara": "555-0123"}
Explanation: "Cara" isn't in the phone book yet, so she is added.

Example 2:

Input: phoneBook = {"Ana": "555-0142", "Ben": "555-0199"}, name = "Ben", number = "555-0100"
Output: {"Ana": "555-0142", "Ben": "555-0199"}
Explanation: "Ben" is already in the phone book. He keeps his old number, "555-0199".

Example 3:

Input: phoneBook = {}, name = "Max", number = "555-0100"
Output: {"Max": "555-0100"}
Explanation: The phone book was empty. Now it has one contact.

 

Constraints:

  • phoneBook can be empty.
  • Names are single words made of English letters.
  • Every phone number has three digits, a dash and four digits, like "555-0142".
  • Two people can share a phone number.
STEP 1 OF 3
    Ctrl + Enter to check

    TYPESCRIPT · DICTIONARIES - CHALLENGES

    Add Contact in TypeScript, explained

    Problem overview

    addContact receives a phone book phoneBook, an object from names to phone numbers (both strings), a name and a number. It adds the name with its number and returns the phone book, but only when the name is not in the phone book yet. A name that is already there keeps its old number. The order of the entries doesn't matter.

    With {"Ana": "555-0142", "Ben": "555-0199"} and "Cara" with "555-0123", Cara is added. With "Ben" and "555-0100" nothing changes, and Ben keeps "555-0199". With an empty phone book, "Max" becomes the only contact.

    Approach

    Assigning to a key replaces any value that is already there. That is why the check must come first: if the key exists, skip the assignment. The check is name in phoneBook, and ! in front of the whole check turns it into "name is not a key yet".

    Step by step

    1. Write the condition. if (!(name in phoneBook)), with the parentheses around the in check. Without them, ! would apply to name alone, and the condition would be wrong for every name. Close the brace right away.
    2. Store the number. Inside the if, phoneBook[name] = number. Assigning to a key that isn't there adds it with its value.
    3. Return the phone book after the if, so it runs in both cases.

    The solution in TypeScript

    class Solution {
        addContact(phoneBook: { [key: string]: string }, name: string, number: string): { [key: string]: string } {
            if (!(name in phoneBook)) {
                phoneBook[name] = number;
            }
            return phoneBook;
        }
    }

    The type { [key: string]: string } says "an object with any string keys and string values". Running the three examples prints:

    { Ana: '555-0142', Ben: '555-0199', Cara: '555-0123' }
    { Ana: '555-0142', Ben: '555-0199' }
    { Max: '555-0100' }

    Why the check comes first

    In an object, writing phoneBook[name] = number does two jobs: it adds the key when it is new, and it overwrites the value when it already exists. Both are the same line of code, so the function cannot tell them apart unless you ask first. That is the purpose of the if: it keeps the second job from happening. The first example takes the if branch because "Cara" is not a key, and the second skips it because "Ben" is.

    Also note that the check looks only at the name. The two numbers in the second example, the old "555-0199" and the new "555-0100", are never compared with each other.

    Edge cases and common mistakes

    • Existing name. Ben keeps "555-0199". Assigning without the check would give him "555-0100", and the printed book would show { Ben: '555-0100' } for that entry.
    • Empty phone book. "Max" in {} is false, so Max is added.
    • Shared numbers. Two names may have the same number. Only the name is checked, never the number.
    • Missing parentheses. !name in phoneBook is read as (!name) in phoneBook. A non-empty name is truthy, so !name is false, and the condition asks whether the key "false" exists. It doesn't, so nothing is ever added: the call with "Cara" returns { Ana: '555-0142' } for a book that held only Ana. The compiler reports a type error here, but the JavaScript still runs and misbehaves.
    • The parameter named number. It is allowed as a parameter name. TypeScript's type number and a variable called number live in different places, so there is no clash.
    • The function changes the book it receives. It returns that same object, not a copy.
    Keep going with TypeScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free