Unlocking JavaScript Type Coercion Magic
Published: 2023-06-22 17:39:50

- <a href="#type-coercion"> Type Coercion </a>
  - <a href="#what-is-type-coercion"> What is Type Coercion? </a>
  - <a href="#different-types-of-type-coercion"> Different Types of Type Coercion? </a>
  - <a href="#implicit-type-conversion-based-on-operator"> Implicit Type Conversion/Coercion Based on Operator </a>
    - <a href="#addition-operator-type-conversion"> Addition Operator (+) Implicit Type Conversion/Coercion </a>
    - <a href="#subtraction-operator-type-conversion"> Subtraction Operator (-) Implicit Type Conversion / Coercion </a>
    - <a href="#division-operator-type-conversion"> Division Operator (/) Implicit Type Conversion / Coercion </a>
    - <a href="#multiplication-operator-type-conversion"> Multiplication Operator (*) Implicit Type Conversion/ Coercion </a>
    - <a href="#greater-than-operator-type-conversion"> Greater Than Operator (>) Implicit Type Conversion / Coercion </a>
    - <a href="#loose-equallity-operator-type-conversion"> Loose Equality Operator (==) Implicit Type Conversion / Coercion </a>
    - <a href="#strict-equallity-operator-type-conversion"> Strict Equality Operator (===) Implicit Type Conversion / Coercion </a>
    - <a href="#logicalAnd-logicalOr-logicalNot-operator-type-conversion"> Logical And (&&), Logical OR(||) and Logical NOT (!) Operator Type Conversion / Coercion </a> 
  - <a href="#implicit-type-conversion-for-null-undefined-and-NaN"> Implicit Type Conversion / Coercion for Null, Undefined and NaN </a>
  - <a href="#explict-type-coercion"> Explicit Type Coercion </a>
    - <a href="#string-conversion"> Explicit String Conversion / Coercion </a>
    - <a href="#boolean-conversion"> Explicit Boolean Conversion / Coercion </a>
    - <a href="#number-conversion"> Explicit Number Conversion / Coercion </a>
- <a href="#references"> References </a>


## <span id="type-coercion" style="color:lightcoral; font-weight:700"> Type Coercion </span>

### <span id="what-is-type-coercion" style="color:orange; font-weight:700"> What is Type Coercion? </span>

The terms type coercion, type conversion, type casting, and type juggling all refer to the process of converting one data type to another. This process is extremely important in computer science and can be found in almost every programming language.  
### <span id="different-types-of-type-coercion" style="color:orange; font-weight:700"> Different Types of Type Coercion? </span>

There are `two types of coercion` available in JavaScript. They are `implicit type coercion` and `explicit type coercion`.

**Implicit Type Coercion** is not intentional. This type of coercion is done by Javascript itself. The Developer has no control over implicit type coercion. Most of the unexpected behavior (80%) happens in JavaScript by `implicit type coercion`. Some examples are:

```javascript
console.log(2 * "5") // 10
console.log("12" - "10") // 2
console.log(true + true) // 2
console.log(10 * [6]) // 60
```

**Explicit Type Coercion** is intentional and done by the developers. Developers have full control over explicit type coercion. The code behavior of `explicit type coercion` is obvious and expected. Some examples are:

```javascript
// Number to String
console.log(String(123)); // "123"

// Number to Boolean
console.log(Boolean(2)); // true

// String to Number
console.log(Number("123")); // 123
```

Whether it is implicit or explicit type coercion, JavaScript can only `convert/coerces` to the `string`, `number`, and `Boolean` primitive types. There’s no way in JavaScript to `coerce` a value type to an `object` or `function`. 


### <span id="implicit-type-conversion-based-on-operator" style="color:orange; font-weight:700"> Implicit Type Conversion/Coercion Based on Operator </span>

### <span id="addition-operator-type-conversion" style="color:orange; font-weight:700"> Addition Operator (+) Implicit Type Conversion/Coercion </span>

In JavaScript, the "+" symbol is used for addition. The "+" operator performs calculations from left to right. Here are some examples of implicit type coercion using the addition operator, along with their explanations.

`Note:` You will see comments like the following. Here nested comments are same-line comments. I wrote nested comments for enhancing readability.

```javascript
// "+" operator work left to right so that
  // first it add two number and then convert 
  // them to string
// ==> 18 + "number"
// ==> "18number"
```

```javascript
// "+" operator work left to right so that first it add two number and then convert them to string
// ==> 18 + "number"
// ==> "18number"
```



```javascript
console.log(true + false); // 1
// true coerces to 1 and false coerces to 0
// ==> 1 + 0
// ==> 1

console.log(true + true); // 2
// true coerces to 1 and false coerces to 0
// ==> 1 + 1
// ==> 2

console.log(false + false); // 0
// true coerces to 1 and false coerces to 0
// ==> 0 + 0
// ==> 2

console.log("1" + 1); // "11"
// "+" operator work left to right
// ==> "1" + 1
// ==> "11"

console.log("4" + true); // "4true"

// Exception: Symbol cannot convert to string
console.log("" + Symbol("my symbol")); 
// TypeError: Cannot convert a Symbol value to a string

console.log("number" + 15 + 3); // "number153"
// "+" operator work left to right
// ==> "number15" + 3
// ==> "number153"

console.log(15 + 3 + "number"); // "18number"
// "+" operator work left to right so that
  // first it add two number and then convert 
  // them to string
// ==> 18 + "number"
// ==> "18number"

console.log("foo" + +"bar"); // "fooNaN"
// Here (+"bar"), "+" operator act like 
  // unary plus operator, which tries to 
  // convert its operand into a number. 
  // Since the operand is the string "bar", 
  // which cannot be directly converted into a number, 
  // it results in NaN
// ==> "foo" + (+"bar")
// ==> "foo" + NaN
// ==> "fooNaN"

console.log({} + {}); // "[object Object][object Object]"
// curly brace {} represent empty object 
  // and converted to "[object Object]"
// ==> "[object Object]" + "[object Object]"
// ==> "[object Object] [object Object]"

console.log({} + []); // "[object Object]"
// curly brace {} represent empty object 
  // and converted to "[object Object]" and 
  // empty array [] converted to empty string ""
// ==> "[object Object]" + ""
// ==> "[object Object]"

console.log([] + []); // ""
// empty array [] converted to empty string ""
// ==> "" + ""
// ==> ""

console.log([1] + []); // "1"
// when you use the "+" operator with arrays, 
  // it performs array-to-string conversion
// ==> "1" + ""
// ==> "1"

console.log([1, 2] + []); // "1,2"
// when you use the "+" operator with arrays, 
  // it performs array-to-string conversion
// ==> "1,2" + ""
// ==> "1,2"

console.log(!([1] + [])); // false
// If logical operator (&&, ||, !) used in 
  // implicit coercion, then it will give 
  // output in boolean
// !("1") : "1" is truthy value so !("1") = false
// ==> !("1" + "")
// ==> !("1")
// ==> false


console.log({} + [] + {} + [1]); // "[object Object][object Object]1"
// ==> "[object Object]" + "" + "[object Object]" + "1"
// ==> "[object Object][object Object]1"

console.log(!+[] + [] + ![]); // "truefalse"
// +[]: The + operator is used here as the 
  // unary plus operator, which tries to convert 
  // its operand into a number. The operand [] 
  // represents an empty array, which is coerced 
  // into the number 0. So +[] evaluates to 0.
// !0: As 0 is a falsy value so !0 will be true
// ![]: An empty array is considered a truthy value, 
  // so ![] evaluates to false.
// ==> (!+[]) + [] + (![])
// ==> !0 + [] + false
// ==> true + [] + false
// ==> true + "" + false
// ==> "truefalse"

```



### <span id="subtraction-operator-type-conversion" style="color:orange; font-weight:700"> Subtraction Operator (-) Implicit Type Conversion / Coercion </span>

The `-` symbol is the subtraction operator in JavaScript. When applied to a string and a number, JavaScript automatically tries to convert the string to a number before performing the subtraction.

```javascript
console.log("10" - 10); // 0
// ==> 10 - 10
// ==> 0

console.log(10 - "10"); // 0
// ==> 10 - 10
// ==> 0

console.log("2" - 1); // 1
// ==> 2 - 1
// ==> 1
```


### <span id="division-operator-type-conversion" style="color:orange; font-weight:700"> Division Operator (/) Implicit Type Conversion / Coercion </span>

The `/` symbol is the division operator in JavaScript. When applied to a string and a number, JavaScript automatically tries to convert the string to a number before performing the division.

```javascript
console.log(12 / 6); // 2
// ==> 2

console.log(12 / "6"); // 2
// ==> 12 / 6
// ==> 2

console.log("12" / "6"); // 2
// ==> 12 / 6
// ==> 2
```


### <span id="multiplication-operator-type-conversion" style="color:orange; font-weight:700"> Multiplication Operator (*) Implicit Type Conversion/ Coercion </span>

The `*` symbol is the multiplication operator in JavaScript. When applied to a number and a string, JavaScript automatically tries to convert the string to a number before performing the multiplication.

```javascript
console.log(12 * 6); // 72
// ==> 72

console.log(12 * "6"); // 72
// ==> 12 * 6
// ==> 72

console.log("12" * "6"); // 72
// ==> 12 * 6
// ==> 72
```


### <span id="greater-than-operator-type-conversion" style="color:orange; font-weight:700"> Greater Than Operator (>) Implicit Type Conversion / Coercion </span>

In JavaScript, when comparing values using the Greater Than `>` operator, both operands are automatically converted to numbers before the comparison is made.

```javascript
console.log(6 > "5"); // true
// ==> 6 > 5
// ==> true

console.log("6" > "45"); // true
// When comparing characters, JavaScript compares 
  // their leftmost Unicode values (UTF-16).
// The first character of "6" is "6", 
  // and the first character of "45" is "4".
// The Unicode value of "6" is 54 and "4" is 52. 
  // So "6" is greater than "4". 
  // Thats why it evaluates to true
// Unicode table: https://asecuritysite.com/coding/asc2
// ==> "6" > "4"
// ==> 54 > 52 
// ==> true

console.log("6" > "75"); // false
// When comparing characters, JavaScript compares 
  // their leftmost Unicode values (UTF-16).
// The first character of "6" is "6", 
  // and the first character of "75" is "7".
// The Unicode value of "6" is 54 and "7" is 55. 
  // So "7" is greater than "6" 
  // Thats why it evaluates to flase
// Unicode table: https://asecuritysite.com/coding/asc2
// ==> "6" > "7"
// ==> 54 > 55
// ==> flase
```

### <span id="loose-equallity-operator-type-conversion" style="color:orange; font-weight:700"> Loose Equality Operator (==) Implicit Type Conversion / Coercion </span>

Loose equality operator (==) operator performs type coercion before making the comparison. After the type coercion, the loose equality operator (==) checks only the equality of values and ignores the original types.

```javascript
console.log("true" == true); // false
// "true" trying to convert it into number. 
  // But as it is not a number so it returns NaN
// true convert it into number 1
// ==> "true" == true
// ==> NaN == 1
// ==> false

console.log(false == "false"); // false
// ==> 0 == NaN
// ==> false

console.log(!!"false" == !!"true"); // true
// ==> !!NaN == !!NaN
// ==> !true == !true
// ==> false == false
// ==> true

console.log(["x"] == "x"); // true
// ==> "x" == "x"
// ==> true

console.log(10 == "10"); // true
// Here string type coerces into number befor comparison.
// Now both values are same. So that it retun true
// ==> 10 == 10
// true

console.log([10] == 10); // true
// First, Array coerces to string
// Then string type coerces into number before comparison.
// Now both values are same. So that it retun true
// ==> "10" == 10
// ==> 10 == 10
// ==> true

console.log([10] == "10"); // true
// First, Array converted to string
// Now both values are same. So that it retun true
// ==> "10" == "10"
// ==> true
```

### <span id="strict-equallity-operator-type-conversion" style="color:orange; font-weight:700"> Strict Equality Operator (===) Implicit Type Conversion / Coercion </span>

The Strict equality operator (===) operator does not perform type coercion. It performs strict equality comparison so checking both value and type.

```javascript
console.log(10 === "10"); // false
// The number 10 is a numeric value, 
  // while the string "10" is a string value.
// As type doesn't match thats why they return false

console.log([10] === 10); // false
// The array [10] is an object type, 
  // while the number 10 is a number type.
// As type doesn't match thats why they return false

console.log([10] === "10"); // false
// The array [10] is an object type, 
  // while the string 10 is a string type.
// As type doesn't match thats why they return false
```


### <span id="logicalAnd-logicalOr-logicalNot-operator-type-conversion" style="color:orange; font-weight:700"> Logical And (&&), Logical OR(||) and Logical NOT (!) Operator Type Conversion / Coercion </span>

When evaluating a logical AND operation, JavaScript follows these rules:
  - If the first operand is truthy (not equal to false, null, undefined, 0, NaN, or an empty string), the second operand is returned.
  - If the first operand is falsy, it is returned without evaluating the second operand.

When evaluating a logical OR operation, JavaScript follows these rules:
  - If the first operand is `truthy`, it is returned without evaluating the second operand.
  - If the first operand is falsy (equal to false, null, undefined, 0, NaN, or an empty string), the second operand is returned.

```javascript
// logical operator internally convert to Boolean 
  // but it returns in original value 
// the following expression will returns 
  // number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean 
  // internally to calculate the expression
console.log('hello' && 123); // 123
// In this case, "hello" is a non-empty string, 
  // which is a `truthy` value in JavaScript. 
  // Therefore, the logical AND operation continues 
  // to evaluate the second operand, 123.


console.log("hello" || 123); // "hello"
// In this case, "hello" is a non-empty string, 
  // which is a `truthy` value in JavaScript. 
  // Therefore, the logical OR operation returns 
  //the truthy value of the first operand, 
  // which is "hello"

console.log(![]); // false
// ![] : [] is truthy value so ![] = false

console.log([] == ![]); // true
// The loose equality operator (==) operator 
  // in JavaScript performs type coercion 
  // before making the comparison.
// ==> "" == false
// ==> 0 == 0
// true

console.log([] === ![]); // false
// Strict equality operator does not perform 
// type coercion and check type & value
// ==> [] == false
// ==> false

console.log(!4); // false

console.log(!!4); // true
```


### <span id="implicit-type-conversion-for-null-undefined-and-NaN" style="color:orange; font-weight:700"> Implicit Type Conversion / Coercion for Null, Undefined and NaN </span>

- **Null implicit type coercion** :

  ```javascript
  console.log(null + null); // 0
  // null coerces to O. 
  // ==> 0 + 0
  // ==> 0

  console.log(null + 3); // 3
  // null coerces to O. 
  // ==> 0 + 3
  // ==> 3

  console.log(null - 3); // -3
  // null coerces to O. 
  // ==> 0 -3
  // ==> -3

  console.log("4" + null); // "4null"

  console.log([] + null + 1); // "null1"
  // ==> "" + null + 1
  // ==> "null" + 1
  // ==> "null1"

  console.log(null > 0); // false
  // ==> 0 > 0
  // ==> false

  console.log(null < 3); // 3
  // ==> 0 < 3
  // ==> true

  console.log(null + ""); // "null"
  // ==> null + ""
  // ==> "null"

  console.log(null + "3"); // null3
  // ==> null + "3"
  // ==> "null3"

  console.log(null == null); // true
  // If you compare null with null 
    // or undefined you will get true. 
    // Rest of the case it will return false.

  console.log(null === null); // true

  console.log(null == ""); // false

  console.log(null == 5); // false

  console.log(null === 5); // false

  console.log(null == true); // false

  console.log(null == false); // false

  console.log(null == NaN); // false
  ```


- **Undefined implicit type coercion** :
  

  ```javascript
  console.log(undefined + undefined); // NaN
  // undefined coerces to NaN
  // ==> NaN + 0
  // ==> NaN

  console.log(undefined + 3); // NaN
  // ==> NaN + 3
  // ==> NaN

  console.log(undefined - 3); // NaN
  // ==> NaN -3
  // ==> NaN

  console.log("4" + undefined); // "4undefined"
  // ==> "4" + undefined
  // ==> "4undefined"

  console.log(undefined > 4); // false
  // When comparing undefined with any 
  // value using a relational operator like >, 
  // JavaScript treats undefined as NaN (Not-a-Number).
  // ==> NaN > 4
  // false

  console.log(undefined == ""); // false
  // If you compare undefined with null 
    // or undefined you will get true. 
    // Rest of the case it will return false.

  console.log(undefined == true); // false

  console.log(undefined == false); // false

  console.log(undefined == undefined); // true

  console.log(undefined === undefined); // true

  console.log(undefined == NaN); // false
  ```

- **Null and Undefined type coercion together**

  ```javascript
  console.log(null + undefined); // NaN
  // null and undefined are not numeric values. 
    // In this case, JavaScript tries to convert them 
    // into numbers
  //  null is coerced into a number, it becomes 0
  // undefined is coerced into a number, 
    // it becomes NaN (Not-a-Number)
  // When we add 0 with NaN, the result is NaN.
  // ==> 0 + NaN
  // ==> NaN

  console.log(null - undefined); // NaN
  // null and undefined are not numeric values. 
    // In this case, JavaScript tries to convert 
    // them into numbers
  //  null is coerced into a number, it becomes 0
  // undefined is coerced into a number, 
    // it becomes NaN (Not-a-Number)
  // When we subtract 0 with NaN, 
    // the result is NaN.
  // ==> 0 - NaN
  // ==> NaN

  console.log(null == undefined); // true
  // If you compare null/undefined with null or 
    //undefined you will get true. 
    // Rest of the case it will return false.

  console.log(null === undefined); // false
  // null is an object type, 
    // while undefined is a undefined type.
  // As type doesn't match thats why they return false
  ```

- **NaN implicit type coercion**

  ```javascript
  console.log(NaN + NaN); // NaN
  // ==> NaN + NaN
  // ==> NaN

  console.log(NaN + 3); // NaN
  // ==> NaN + 3
  // ==> NaN

  console.log(NaN - 3); // NaN
  // ==> NaN - 3
  // ==> NaN

  console.log("4" + NaN); // "4NaN"
  // ==> "4" + NaN
  // ==> "4NaN"

  console.log([] + NaN + 1); // "NaN1"
  // ==> "" + NaN + 1
  // ==> "NaN" + 1
  // ==> "NaN1"

  console.log(NaN > 0); // false
  // Any comparison involving NaN evaluates to false.
  // NaN is not a valid number, 
    // and thus cannot be compared to     
    // any other value, even to itself.

  console.log(NaN < 3); // false

  console.log(NaN + ""); // "NaN"
  // ==> NaN + ""
  // ==> "NaN"

  console.log(NaN + "3"); // "NaN3"
  // ==> NaN + "3"
  // ==> "NaN3"

  console.log(NaN == NaN); // false

  console.log(NaN === NaN); // false

  console.log(NaN == ""); // false

  console.log(NaN == true); // false

  console.log(NaN == false); // false

  console.log(null == NaN); // false
  ```

### <span id="explict-type-coercion" style="color:orange; font-weight:700"> Explicit Type Coercion </span>

We know that, Whether it is implicit or explicit type coercion, JavaScript can only `convert/coerces` to the `string`, `number`, and `Boolean` primitive types. There’s no way in JavaScript to `coerce/convert` a value type to an `object` or `function`. 

### <span id="string-conversion" style="color:orange; font-weight:700"> Explicit String Conversion / Coercion </span>

Explicitly we can convert anything to a string with JavaScript `String()` method.

```javascript
console.log(String(43)); // "43"
console.log(String(-43.3)); // "43.3"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
console.log(String(NaN)); // NaN
console.log(String(true)); // "true"
console.log(String(false)); // "false"
console.log(String(Symbol("my symbol"))); // "Symbol(my symbol)"
```


### <span id="boolean-conversion" style="color:orange; font-weight:700"> Explicit Boolean Conversion / Coercion </span>

Explicitly we can convert anything to a boolean with JavaScript `Boolean()` method.

We know that a boolean only return `true` or `false`. Boolean that only returns `falsy` values is the following:

```javascript
console.log(Boolean("")); // false
console.log(Boolean(0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(false)); // false
```

Anything except the above list will return `true`. The following list will return `true`.  

```javascript
console.log(Boolean({})); // true
console.log(Boolean([])); // true
console.log(Boolean(Symbol())); // true
console.log(!!Symbol()); // true
console.log(Boolean(function () {})); // true
```

### <span id="number-conversion" style="color:orange; font-weight:700"> Explicit Number Conversion / Coercion </span>

Explicitly we can convert anything to a Number or NaN (not-a-number) with JavaScript `Number()` method.

```javascript
console.log(Number(123)); // 123
console.log(Number(" 12s ")); // NaN
console.log(Number(" 12 ")); // 12
console.log(Number("-12.34")); // -12.34
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(NaN); // NaN
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number("\\n")); // NaN
```

## <span id="references" style="color:lightcoral; font-weight:700"> References </span>

- [Type Coercion in JavaScript](https://javascript.plainenglish.io/type-coercion-in-javascript-ef5e390d2318)
- [JavaScript type coercion explained](https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/)
- [JavaScript Type Conversions](https://www.programiz.com/javascript/type-conversion)
- [JavaScript - Type Coercion Explained](https://stacklearner.com/javascript-type-coercion-explained)
- [Javascript Tricky Questions — Type Coercion](https://eishta.medium.com/javascript-tricky-questions-type-coercion-7fe47b4c488e)

### Thanks for reading ✨! 
Connect with me on [LinkedIn](https://www.linkedin.com/in/shourovrahman/) 

Don't forget to share your thoughts in the comment section.