# JavaScript Type Conversions

Type conversion (also known as type coercion) is one of JavaScript's most powerful yet often misunderstood features. Whether you're converting strings to numbers, booleans to integers, or arrays to strings, understanding these conversions will make you a more effective JavaScript developer.

## String to Number Conversions

### The Unary Plus Operator (+)

The fastest and most concise way to convert a string to a number:

```javascript
+"42"           // 42
+"3.14"         // 3.14
+"-10"          // -10
+"0xFF"         // 255 (hex notation works!)
```

**Watch out for edge cases:**

```javascript
+"123abc"       // NaN
+""             // 0 (empty string becomes 0)
+" "            // 0 (whitespace becomes 0)
```

### The Double Bitwise NOT (~~)

Great for converting to integers, as it truncates decimals:

```javascript
~~"42"          // 42
~~"3.14"        // 3 (truncates decimal)
~~"-10"         // -10
```

**Important difference:**

```javascript
+"123abc"       // NaN
~~"123abc"      // 0 (returns 0 instead of NaN)
```

### Number() Constructor

More explicit and readable:

```javascript
Number("42")         // 42
Number("3.14")       // 3.14
Number("")           // 0
Number("abc")        // NaN
```

### parseInt() and parseFloat()

The classic methods, especially useful for strings with mixed content:

```javascript
parseInt("42")       // 42
parseInt("42px")     // 42 (stops at first non-digit)
parseInt("3.14")     // 3 (always returns integer)
parseFloat("3.14")   // 3.14
parseFloat("3.14px") // 3.14
```

**Pro tip:** Always specify the radix with parseInt:

```javascript
parseInt("10", 10)   // 10 (decimal)
parseInt("10", 2)    // 2 (binary)
parseInt("FF", 16)   // 255 (hexadecimal)
```

### Arithmetic Tricks

Multiplication and subtraction force type conversion:

```javascript
"42" * 1             // 42
"3.14" * 1           // 3.14
"42" - 0             // 42
"100" - 20           // 80
```

## Number to String Conversions

### String Concatenation

The simplest approach:

```javascript
42 + ""              // "42"
3.14 + ""            // "3.14"
(1 + 2) + ""         // "3"
```

### Template Literals

Modern and readable:

```javascript
`${42}`              // "42"
`${3.14}`            // "3.14"
`Value: ${100}`      // "Value: 100"
```

### String() Constructor

Explicit conversion:

```javascript
String(42)           // "42"
String(3.14)         // "3.14"
String(null)         // "null"
String(undefined)    // "undefined"
```

### toString() Method

Offers base conversion options:

```javascript
(42).toString()      // "42"
(255).toString(16)   // "ff" (hexadecimal)
(8).toString(2)      // "1000" (binary)
(255).toString(8)    // "377" (octal)
```

### Formatting Methods

For precise decimal control:

```javascript
(3.14159).toFixed(2)     // "3.14"
(42).toFixed(2)          // "42.00"
(1234).toExponential()   // "1.234e+3"
(123.456).toPrecision(4) // "123.5"
```

## Boolean Conversions

### To Boolean: The Double NOT (!!)

The standard way to convert any value to boolean:

```javascript
!!"hello"            // true
!!1                  // true
!!0                  // false
!!""                 // false
!!null               // false
!!undefined          // false
```

**Important:** Arrays and objects are always truthy:

```javascript
!![]                 // true (empty array is truthy!)
!!{}                 // true (empty object is truthy!)
!!" "                // true (non-empty string)
```

### Boolean() Constructor

More explicit alternative:

```javascript
Boolean("hello")     // true
Boolean(0)           // false
Boolean([])          // true
```

### From Boolean to Other Types

Converting booleans to numbers:

```javascript
true + 0             // 1
false + 0            // 0
+true                // 1
+false               // 0
Number(true)         // 1
Number(false)        // 0
```

Converting booleans to strings:

```javascript
true + ""            // "true"
false + ""           // "false"
String(true)         // "true"
`${false}`           // "false"
```

## Array and String Conversions

### Array to String

Using join():

```javascript
[1, 2, 3].join()         // "1,2,3"
[1, 2, 3].join("")       // "123"
[1, 2, 3].join("-")      // "1-2-3"
["a", "b", "c"].join(" ")// "a b c"
```

Quick conversion:

```javascript
[1, 2, 3].toString()     // "1,2,3"
[1, 2, 3] + ""           // "1,2,3"
`${[1, 2, 3]}`           // "1,2,3"
```

### String to Array

Multiple approaches:

```javascript
// Split method
"hello".split("")            // ['h', 'e', 'l', 'l', 'o']
"a,b,c".split(",")           // ['a', 'b', 'c']
"one two three".split(" ")   // ['one', 'two', 'three']

// Spread operator (ES6+)
[..."hello"]                 // ['h', 'e', 'l', 'l', 'o']
[..."abc"]                   // ['a', 'b', 'c']

// Array.from()
Array.from("hello")          // ['h', 'e', 'l', 'l', 'o']
```

## Object Conversions

### Object to Array

```javascript
const obj = {a: 1, b: 2, c: 3};

Object.keys(obj)             // ['a', 'b', 'c']
Object.values(obj)           // [1, 2, 3]
Object.entries(obj)          // [['a', 1], ['b', 2], ['c', 3]]
```

### Array to Object

```javascript
// From entries
Object.fromEntries([['a', 1], ['b', 2]])
// Result: {a: 1, b: 2}

// Using reduce
['a', 'b', 'c'].reduce((acc, val, i) => ({...acc, [val]: i}), {})
// Result: {a: 0, b: 1, c: 2}

// From keys with default value
Object.fromEntries(['a', 'b', 'c'].map(k => [k, 0]))
// Result: {a: 0, b: 0, c: 0}
```

### JSON Conversions

```javascript
const obj = {name: "Alice", age: 25};

// Object to JSON string
JSON.stringify(obj)
// '{"name":"Alice","age":25}'

JSON.stringify(obj, null, 2)
// Formatted with 2-space indentation

// JSON string to Object
JSON.parse('{"name":"Alice","age":25}')
// {name: 'Alice', age: 25}
```

## Special Cases and Gotchas

### Null and Undefined Handling

Default values with nullish coalescing:

```javascript
null ?? "default"        // "default"
undefined ?? "default"   // "default"
0 ?? "default"           // 0 (not null/undefined)
"" ?? "default"          // "" (not null/undefined)
```

Default values with logical OR:

```javascript
null || "default"        // "default"
0 || "default"           // "default" (0 is falsy)
"" || "default"          // "default" (empty string is falsy)
false || "default"       // "default"
```

### Weird Coercions You Should Know

These might surprise you:

```javascript
[] + []                  // "" (empty string!)
[] + {}                  // "[object Object]"
{} + []                  // 0 (in some contexts)
[] == false              // true
"0" == 0                 // true (loose equality coerces)
"0" === 0                // false (strict equality doesn't)
null == undefined        // true
null === undefined       // false
```

### Math Operations

Addition vs other operators:

```javascript
"5" + 3                  // "53" (concatenation)
"5" - 3                  // 2 (conversion)
"5" * "2"                // 10 (both convert)
"10" / "2"               // 5 (both convert)
```

### Date Conversions

```javascript
const date = new Date("2024-01-15");

// Date to timestamp
+date                    // 1705276800000
date.getTime()           // 1705276800000

// Date to string
date.toISOString()       // "2024-01-15T00:00:00.000Z"
date.toLocaleDateString()// "1/15/2024"

// Timestamp to date
new Date(1705276800000)  // Mon Jan 15 2024
```

### Number Base Conversions

```javascript
// Decimal to other bases
(255).toString(16)       // "ff" (hex)
(255).toString(2)        // "11111111" (binary)
(255).toString(8)        // "377" (octal)

// Other bases to decimal
parseInt("ff", 16)       // 255
parseInt("11111111", 2)  // 255
parseInt("377", 8)       // 255

// Formatting
(255).toString(16).toUpperCase()  // "FF"
(10).toString(2).padStart(8, "0") // "00001010"
```

## Best Practices

### 1\. Be Explicit When It Matters

For production code, explicit conversions are often clearer:

```javascript
// Good
Number(userInput)
String(value)
Boolean(condition)

// Clever but less clear
+userInput
value + ""
!!condition
```

### 2\. Use Strict Equality

Always use `===` instead of `==` to avoid unexpected coercion:

```javascript
// Avoid
if (value == 0) { }      // Could match "", [], false

// Prefer
if (value === 0) { }     // Only matches 0
```

### 3\. Handle NaN Properly

```javascript
// Wrong way
value === NaN            // Always false (NaN !== NaN)

// Right way
Number.isNaN(value)      // true only for NaN
isNaN(value)             // true if value converts to NaN
```

### 4\. Validate Before Converting

```javascript
// Safe conversion function
const toNumber = (str) => {
  const num = +str;
  return isNaN(num) ? 0 : num;
};

toNumber("42")           // 42
toNumber("abc")          // 0 (safe fallback)
```

### 5\. Choose the Right Method

**For integers from strings:** Use `parseInt()` with radix

```javascript
parseInt("42", 10)       // Always specify base
```

**For floats from strings:** Use `parseFloat()` or `Number()`

```javascript
parseFloat("3.14")
Number("3.14")
```

**For formatting numbers:** Use `toFixed()`, `toPrecision()`

```javascript
(3.14159).toFixed(2)     // "3.14"
```

**For boolean checks:** Use `Boolean()` or `!!`

```javascript
if (Boolean(value)) { }
if (!!value) { }
```

## Practical Examples

### CSV String to Number Array

```javascript
"1,2,3,4,5".split(",").map(Number)
// [1, 2, 3, 4, 5]
```

### RGB to Hex Color

```javascript
const rgbToHex = (r, g, b) => 
  "#" + [r, g, b].map(x => x.toString(16).padStart(2, "0")).join("");

rgbToHex(255, 0, 128)    // "#ff0080"
```

### Hex to RGB Color

```javascript
const hexToRgb = hex => 
  hex.match(/[A-Fa-f0-9]{2}/g).map(x => parseInt(x, 16));

hexToRgb("#ff0080")      // [255, 0, 128]
```

### Query Parameters to Object

```javascript
const params = "?name=Alice&age=25";
Object.fromEntries(new URLSearchParams(params))
// {name: 'Alice', age: '25'}
```

### Safe Integer Conversion

```javascript
const toInt = (value, defaultValue = 0) => {
  const num = parseInt(value, 10);
  return isNaN(num) ? defaultValue : num;
};

toInt("42")              // 42
toInt("abc")             // 0
toInt("abc", -1)         // -1
```

## Conclusion

JavaScript's type conversion system is flexible and powerful, but it requires understanding to use effectively. Remember these key points:

* Use explicit conversions (`Number()`, `String()`, `Boolean()`) for clarity
    
* Be aware of falsy values: `false`, `0`, `""`, `null`, `undefined`, `NaN`
    
* Empty arrays and objects are truthy
    
* Use `===` instead of `==` to avoid unexpected coercion
    
* Validate and handle edge cases like `NaN`, `null`, and `undefined`
    
* Choose the right method for the job: `parseInt()` for integers, `parseFloat()` for decimals
    
* Test your conversions thoroughly, especially with user input
    

Master these conversions, and you'll write more robust, predictable JavaScript code!
