JavaScript type conversions explained
Tags: javascript
Published: 2022-08-14 13:08:38

by [Eni Onyedikachi](https://blog.openreplay.com/authors/eni-onyedikachi)

Javascript is a weakly typed language, which means different datatypes for variables and objects are not explicitly specified, but done implicitly by the Javascript engine at compile time. Leaving this critical task to the Javascript engine sometimes causes problems in our programs that we are not even aware of. This is why it is important to know how type conversion works in Javascript, which is the main source of logical errors.
 
In this article we will learn:
-  What is type conversion?
-  How primitive and object types are converted
-  The difference between implicit and explicit type conversion
-  Why you should use `===` instead of `==`
-  The algorithm Javascript uses to convert objects to primitives
-  What object-to-primitive conversion methods are and how they work


## What is type conversion?

Type conversion as the name implies is simply converting a value from one type to another in Javascript. Both primitive values and objects are both strong candidates for type conversion in Javascript. For Example:

```javascript
20 + "twenty" // => "20 twenty": Number 20 converts to a string

"10" * "10" // => 100: Both strings convert to numbers

let y = 2 - "x" // n == NaN; String 'x' can't convert to a number

y + "values" // => "NaN values": NaN converts to string "NaN" 
```
 
Javascript uses the strict equality(`===`) and loose equality(`==`) comparison operators to test for equality between two values, but type conversion only occurs when the loose equality operator is used. When testing for strict equality using `===`, both the  type  and  value  of the variables we are comparing have to be the same.

```javascript
10 === 10     // true

NaN === NaN   // false
```

In the preceding code, the number `10` is compared with the number `10`, and as expected the expression returns `true`. Both are *numbers*, and share the same *value* of `10`. The only exception to this rule is the `NaN` value, a value of a unique numeric type in Javascript. Two `NaN` values are never equal to each other.

On the flip side, the loose equality operator(`==`) is quite different. When used to compare two values, the two values are compared only after they have been *converted* to a common type.

```javascript
'20' == 20    //true

false == 0    // true
```

The values in the preceding code are converted (coerced) to a common type before they are compared. Whenever type conversion occurs in Javascript, the value(primitive or object) involved can only be converted to strings, numbers, or booleans. Though the conversion logic for primitives and object varies, they are both converted to only these three types.

### Explicit type conversion

When the developer chooses consciously to convert from one type to another, this is known as an explicit type conversion(type casting). The simplest way to perform an explicit type conversion is to use the `Boolean()`, `Number()`, and `String()` functions:

```javascript
Number("5")     // 5
String(true)    // "true" 
Boolean([])     // true
```
All values except `null` and `undefined` has a `toString()` method and the result of this method is usually the same as that returned by the `String()` function.

### Implicit type conversion

Implicit type conversions are performed by certain operators and are sometimes used explicitly for the purpose of type conversion. However, an implicit conversion can also be triggered by a surrounding context. For example using `if (value) {...}`, here `value` is converted to boolean.

```javascript
x + ""      // String(x)

2 + ""      // "2", String(2)

+x          // Number(x)

x-0         // Number(x)

!x          // Boolean(x)

!2          // false, Boolean(!2)
```

The ! operator converts its operand to boolean and negates it.
 

## How primitive types are converted

Remember, there are two types in Javascript: Primitives and Object Types. Let's understand how type conversion works in primitive types.

The conversion of a primitive value is simple, as seen in the preceding table. The Javascript engine uses the `Boolean()`, `Number()` and `String()` functions to convert primitive values.

### String conversion

```javascript
String(1)           // '1'
String("0")         // '0'
String("one")       // 'one'
String(true)        // 'true'
String(false)       // 'false'
String(null)        // 'null'
String(undefined)   // 'undefined' 
String()            // ''
String('')          // ''
String(' ')         // ' '
```

### Numeric conversion

```javascript
Number(1)           // 1
Number("0")         // 0
Number("one")       // NaN
Number(true)        // 1
Number(false)       // 0
Number(null)        // 0
Number(undefined)   // NaN 
Number()            // 0
Number('')          // 0
Number(' ')         // 0
```

### Boolean conversion

```javascript
Boolean(1)          // true
Boolean(0)          // false
Boolean("one")      // true
Boolean(true)       // true
String(false)       // false
Boolean(null)       // false
Boolean(undefined)  // false
Boolean()           // false
Boolean('')         // false
Boolean(' ')        // true
```
The following table summarizes type conversion in primitive types:

| Value | String Conversion | Numeric Conversion | Boolean Conversion |
| -------- | -------- | -------- | -------- |
| 1  | "1"    | 1     | `true`
| 0 | "0"    | 0    | `false`
| "1"  | "1"    | 1     | `true`
| "0"  | `"0"`    | 0     | `true`
| "one"  | `"one"`    | `NaN`     | `true`
| `true`  | "true"    | 1     | `true`
| `false`  | "false"    | 0     | `false`
| `null`  | "null"    | 0     | `false`
| `undefined`  | "undefined"    | `NaN`     | `false`
| ''  | ''    | 0     | `false`
| ' '  | ' '    | 0     | `true`



## Open Source Session Replay

_[OpenReplay](https://github.com/openreplay/openreplay) is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._

![replayer.png](https://static.openreplay.com/images/banner-blog.png)

_Start enjoying your debugging experience - [start using OpenReplay for free](https://github.com/openreplay/openreplay)._


 

## How object types are converted

Object-to-primitive conversion occurs in the context where an object is used instead of a primitive value. For example, when objects are added `obj_1 + obj_2`, substracted `obj_1 - obj_2` or printed using `alert(obj)`. Javascript uses the [`Toprimitive`](https://tc39.es/ecma262/#sec-toprimitive) algorithm for object-to-primitive conversion. This algorithm allows you to choose how an object should be converted(using one of the  *object-to-primitive conversion methods*) depending on the context in which the object is being used (which is determined through *hints*).

Conceptually, the `[ToPrimitive]` algorithm can be said to be the composite of two aggregate parts: Hints and  Object-to-primitive conversion methods.

![1](https://blog.openreplay.com/static/97b6b08507286584934528cc205fb8b4/582e9/image01.png)

###  Hints 

Hints are signals the `[ToPrimitive]` algorithm uses to determine what an object should be converted to in a particular context. There are three variants:

- `"string"`: In the context where an operation expects a string, if a conversion to string is possible, like `alert()` or the built-in `String()` function.

```javascript=
// output
alert(obj);

//output
String(obj)

// using object as a property key
anotherObj[obj] = 1000; 
```

- `"number"`: In the context where an operation expects a number if such a conversion is possible.

```javascript=
// explicit conversion
let num = Number(obj);

// maths (except binary plus)
let x = +obj; // unary plus
let difference = Date1 - Date2; // date objects

// less/greater comparison
let less = Obj1 < obj2;
```

- `"default"`: Happens in rare cases, in the context where an operator expresses no preference about what type of primitive value is expected; i.e., it is "not sure" of what type to expect.

For example, the binary `+` operator works both with strings(concatenates them) and numbers(adds them), so the object can be converted to both a string or number in this case. Or when an object is compared to a string, number, or symbol using the loose equality `==` operator.

```javascript=
// binary plus
let sum = obj1 + obj2;

// obj == string/number/symbol
if (obj == 10 ) { ... };
```

All [built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) (except Date) implement the `"default"` hint as `"number"`. Date implements the `"default"` hint as `"string"`.

*N/B*: There are only three hints. It's that straightforward. There is no "boolean" hint (all objects are true in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, as most built-in objects do, then there are only two conversions.

###  Object-to-primitive Conversion Methods 

After the  `[ToPrimitive]` algorithm has identified the primitive value an object should convert to based on the hint. The object is then converted to the primitive value using  Object-to-primitive conversion methods.

There are three variants:

- **toString/valueOf**: The `toString()` and `valueOf()` are inherited by all objects in Javascript. They are used for the sole purpose of object-to-primitive conversions. The `[ToPrimitive]` algorithm first tries the `toString()` method. If the method is defined it returns a primitive value, then Javascript uses the primitive value(even if it is not a string!). If `toString()` returns an object or does not exist, then Javascript tries the `valueOf()` method. If that method exists and returns a primitive value, Javascript uses that value. Otherwise, the conversion fails with a `TypeError`.

* `toString -> valueOf` for "string" hint.
* `valueOf -> toString` otherwise.

```javascript=
let Person = {
  name: "Mary",
  age: 22,

  // for hint="string"
  toString() {
    return `{name: "${this.name}"}`;
  },

  // for hint="number" or "default"
  valueOf() {
    return this.age;
  }
};

alert(Person); // toString -> {name: "Mary"}
alert(+Person); // valueOf -> 22
alert(Person + 10); // valueOf -> 32
```

In the preceding code, `Person` becomes a self-descriptive string or number depending on the conversion context. The `toString()` method is used for conversion for `hint="string"` and `valueOf()` is used otherwise(`"number" or "default"`).

However, you may want to handle all your conversions in a single place. In that case, you can implement only the `toString()` method like this:

```javascript=
let Person = {
  name: "Mary",

  toString() {
    return this.name;
  }
};

alert(Person); // toString -> Mary
alert(Person + 1000); // toString -> Mary1000
```

- **Symbol.toPrimitive**: Unlike the `toString()` and `valueOf()` methods that have existed since antiquity, the `Symbol.toPrimitive` is a well-known Symbol in ES6. It allows you to override the default object-to-primitive conversion (where the `toString()` and `valueOf` methods are used by the `[ToPrimitive]` algorithm) in Javascript and define how you want objects to be converted to primitive values. To do this define a method with this symbolic name like this:

```javascript
obj[Symbol.toPrimitive] = function(hint) {
  // return a primitive value
  // hint = one of "string", "number", "default"
}
```

For example, here the `Person` object does the same as above using `Symbol.toPrimitive`

```javascript
let Person = {
  name: "Mary",
  age: 22,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.age;
  }
};

// conversions demo:
alert(Person); // hint: string -> {name: "Mary"}
alert(+Person); // hint: number -> 22
alert(Person + 10); // hint: default -> 32
```

In the preceding code, we can see that the single method `Person[Symbol.toPrimitive]` handles all conversion cases.

*N/B*: In the absence of `Symbol.toPrimitive` and `valueOf()`, `toString()` will handle all primitive conversions.

### Object-to-boolean conversions

All objects convert to true in Javascript—including the wrapper object `new Boolean(false)` and empty array. The object-to-primitive algorithm is not required for object-to-boolean conversion.

### Object-to-string conversions
When an object needs to be converted to a string, Javascript first converts it to a primitive using `[ToPrimitive]` algorithm(hint `"string"`), then converts the derived primitive to a string.

For instance, if you pass an object to a built-in function that expects a string argument like `String()` or when objects are interpolated in [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).

### Object-to-number conversions
When an object needs to be converted to a number, Javascript first converts it to a primitive using `[ToPrimitive]` algorithm(hint `"number"`), then converts the derived primitive to a number. Built-in Javascript functions and methods that expect numeric arguments convert object arguments to numbers this way, e.g `Math()`.

### Special case operator conversions
Type conversion also occurs when the operand of certain Javascript operators is an object, Let's have a detailed look at these operators.

- The  `+`  operator: This operator performs numeric addition and string concatenation. if either of its operands is an object, they are converted to primitive values using the `[ToPrimitive]` algorithm(hint `"default"`). Their types are checked, once they are converted to primitive values. If either argument is a string, it converts the other to a string and concatenates the strings. Otherwise, it converts both arguments to numbers and adds them.

- The `==` and `!==` operators: These operators perform equality and inequality testing in a loose way that enables type conversions. If one operand is an object and the other is a primitive value, these operators convert the object to primitive using the `[ToPrimitive]` algorithm(hint `"default"`) and then compare the two primitive values.

- The `<,<=,>` and `>=` relational operators: The relational operators compare the relationship between two values and can be used to compare both numbers and strings. If either operand is an object, it is converted to a primitive value using the `[ToPrimitive]` algorithm(hint `"number"`). However, unlike the object-to-number conversion, the primitive values returned are not converted to numbers(since they are compared and not used).

## Conclusion

Now you know how type conversion works in Javascript and how to use it. You are more confident and aware of where to use it and when Javascript implicit converts between different types(especially object-to-primitive conversions).

> A TIP FROM THE EDITOR: For more on internal details of JavaScript, check our previous [JavaScript Types and Values, explained](https://blog.openreplay.com/javascript-types-and-values-explained) article.


[![newsletter](https://blog.openreplay.com/static/e6b18eda7a327511296a2f27692f9c70/e9957/newsletter.png)](https://newsletter.openreplay.com/)