Start learning free

LESSON 129 OF 675 · DICTIONARIES

Checking for a Key in TypeScript with the in Operator

Lesson Read the full explanation

TL ; DR:

Write key in obj to ask whether an object has a key. The answer is true or false, so it goes in an if.


const capitals: { [key: string]: string } = {"France": "Paris", "Japan": "Tokyo"};

if ("Japan" in capitals) {
    console.log(capitals["Japan"]);   // Tokyo
}

if (!("Spain" in capitals)) {
    console.log("No Spain");          // No Spain
}


Full lesson:

Reading a missing key doesn't stop the program. capitals["Spain"] just gives undefined.

The type says every key gives a string. Still, a missing key gives undefined when the program runs.

That undefined can travel far before something breaks. So check first.

"Spain" in capitals is true when "Spain" is a key. It is false when it isn't.

For the opposite, put ! before the whole check, in parentheses. Without them, ! applies to "Spain" alone, and the check is always false.

Don't check with if (capitals["Spain"]). A key whose value is "" or 0 would look missing.

A value is not a key

in looks only at the keys. "Paris" in capitals is false, because "Paris" is a value.

A key must match exactly, upper and lower case too. "japan" in capitals is false.


Your task

In pets, each key is a pet's name, and its value is the pet's kind.

First, check whether "Tom" is a key of pets. If it is, log Tom is a followed by Tom's kind.

Then check that "cat" is not a key, with ! and in. If so, log cat is not a key.

"cat" is in pets, but only as a value. It is Tom's kind.

Expected output:

Tom is a cat
cat is not a key
STEP 1 OF 2
    Ctrl + Enter to check

    TYPESCRIPT · DICTIONARIES

    Dictionary Key Check in TypeScript, explained

    Why check first

    In TypeScript, a dictionary is usually an object typed like { [key: string]: string }. Reading a key that isn't there does not stop the program. It just gives undefined:

    const capitals: { [key: string]: string } = {"France": "Paris", "Japan": "Tokyo"};
    console.log(capitals["Spain"]);
    undefined

    The type says every key gives a string, but types are erased when the code is compiled to JavaScript, so nothing checks that at run time. The undefined can travel a long way before something breaks. It is better to ask whether the key exists first.

    The in operator

    key in obj is true when key is a key of obj and false when it isn't. It looks only at the keys, so it fits an if:

    console.log("Japan" in capitals, "Spain" in capitals);
    console.log("Paris" in capitals, "japan" in capitals);
    true false
    false false

    "Paris" is a value, not a key, and a key must match exactly, so "japan" is not "Japan".

    Checking that a key is missing

    For the opposite, wrap the whole check in parentheses and put ! in front: !("Spain" in capitals). Without the parentheses, ! applies to "Spain" alone. A non-empty string is truthy, so !"Spain" is false, and the check becomes false in capitals, which is never what you meant. The compiler reports errors for it (it says the expression is always truthy and that a boolean can't be used as a key), but the JavaScript still runs, and the condition is false every time.

    Using it with else

    The check also answers "which branch should run?". The variable country below holds the key to look up:

    const country = "Spain";
    if (country in capitals) {
        console.log("The capital is " + capitals[country]);
    } else {
        console.log("No capital stored for " + country);
    }
    No capital stored for Spain

    Only the branch where the key exists reads the value, so the code that uses the value can rely on it being there. The same shape works for any lookup whose key comes from somewhere else, such as a name typed by a user.

    The exercise, step by step

    In pets, each key is a pet's name and each value is the pet's kind: Rex is a dog, Tom a cat, Polly a parrot.

    1. Is "Tom" a key? Write an if with the condition "Tom" in pets. Inside it, pets["Tom"] is never undefined, so log "Tom is a " + pets["Tom"].
    2. Is "cat" not a key? Write an if with !("cat" in pets). "cat" is in pets only as a value, Tom's kind, and in looks only at keys, so the condition is true. Log cat is not a key.
    const pets: { [key: string]: string } = {"Rex": "dog", "Tom": "cat", "Polly": "parrot"};
    
    if ("Tom" in pets) {
        console.log("Tom is a " + pets["Tom"]);
    }
    if (!("cat" in pets)) {
        console.log("cat is not a key");
    }
    Tom is a cat
    cat is not a key

    Traps

    • Don't test with the value. if (capitals["Spain"]) treats a key whose value is "" or 0 as missing. With {"a": ""}, that check says the key is missing, while "a" in obj correctly says true.
    • Inherited names. Every object also inherits some names, so "toString" in capitals is true even though you never added it. Ordinary names like those in the lesson are not affected. If it could matter, Object.hasOwn(capitals, "toString") checks only the object's own keys and gives false.
    • Missing parentheses with !. See above: write !("x" in obj).

    Also remember that keys are strings. A number used as a key is turned into text, so 1 in obj and "1" in obj ask the same question. When you build a check from a variable, make sure the variable holds the exact key you stored.

    Key takeaways

    • key in obj is a boolean that looks only at keys.
    • Check before reading, because a missing key reads as undefined.
    • Put the whole in check in parentheses before applying !.
    Keep going with TypeScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free