DEV Community

LV ๐Ÿณ๏ธโ€๐ŸŒˆ
LV ๐Ÿณ๏ธโ€๐ŸŒˆ

Posted on

Coercion Between Primitives and Objects in JavaScript

Every JavaScript developer has read at least one article that describes the unexpected values you get when you perform operations with mismatched types. This is not one of those posts. So relax, I wonโ€™t try to trip you up with type coercion examples.

The idea for this article was born while I was working with Flow, a type checker for JavaScript. While declaring types, I accidentally gave an argument type Boolean and not boolean. I realized there was a casual subtly to my mistake so I wanted to talk about why these two things arenโ€™t the same.

The difference between String and string

There are six primitive types in JavaScript: boolean, string, number, null, undefined, and symbol. Right now weโ€™ll focus on the first three. These three have wrapper objects called Boolean, String, and Number. Youโ€™ve probably used these special wrapper objects when doing an explicit type conversion, e.g.:

    let example = โ€œ6โ€;
    7 === 1 + Number(example)  // true

Since JavaScript is loosely typed, you use implicit type coercion between these types all the time, e.g:

    let example = โ€œThis is a stringโ€;
    example.length  // 16

Here, the JavaScript interpreter sees that you are trying to use a primitive as an object by accessing a property. Since primitives donโ€™t have properties, the interpreter wraps the string primitive in an object by calling String(example) in the background. This allows you to use the primitive like an object.

Boolean vs. boolean and why it matters

For the most part, we can use primitives and wrapper types the same way with no issue. But hereโ€™s a particular case where thatโ€™s not true.

    let example = new Boolean(false);
    if (example) {
        console.log(โ€˜Cats are the bestโ€™);
    } else {
        console.log(โ€˜Dogs are the bestโ€™);
    }

Go ahead and try this example in your console right now.

You might be surprised to see that it prints out โ€˜Cats are the bestโ€™! Since all objects are truthy in JavaScript, example evaluates to true, which can be unintuitive.

Now you know one the reasons why Flow doesnโ€™t let you use primitive and wrapper types interchangeably. I suggest playing around with this over at Flow's playground.

Top comments (0)