JavaScript: Avoid Run-Time Console Errors
Tags: javascript, typescript, codereview, codequality
Published: 2021-09-12 18:48:51

#I HATE RUN-TIME CONSOLE ERRORS

Here, I have said it in big bold capital letters. Usually they arise because you try to access a property of **undefined** or **null**.

You must have been aware of this dreadful image:
![Web console run-time error image](https://i.stack.imgur.com/rN8wT.png "Error")

This happens usually when we try to do something like this:
```javascript
function printPersonDetails(person) {
   console.log(person.age);
}

printPersonDetails(undefined);
```

As soon as you pass person as **undefined** the clock of the doomsday starts ticking and at any moment when this function is triggered, you shall see the run-time error.

You might argue that you could write unit tests but since JavaScript provides all the fallback mechanisms in place then why wait for unit tests to be written.

##Option 1 - Use default values for function parameters
This is the least a developer should do.

###Before
```javascript
function add(a, b, c) {
   return a + b + c;
}

add(1, undefined, 2); // Run-time error
```

###After
```javascript
function add(a=0, b=0, c=0) {
   return a + b + c;
}

add(1, undefined, 2); // Run-time error
```

Providing default values to parameters is a good practice.

##Option 2 - Nullish coalescing operator (??)
This **(??)** new symbol is a life saver. This is a logical operator that returns RHS operator if LHS is null/undefined.
RHS/LHS - right/left hand side (duh!)

I 💗 this feature!

```javascript
function add(a, b, c) {
 const valOfA = a ?? 0;
 const valOfB = b ?? 0;
 const valOfC = c ?? 0;
 return a + b + c;
}

add(null, undefined, null); // Run-time error
```

##Option 3 - Logical Nullish assignment operator (??=)
This **(??=)** new symbol is another life saver. The logical nullish assignment **(x ??= y)** operator only assigns if **x** is **nullish (null or undefined)**.

I 💗 this feature!

```javascript
function printPersonDetails(person) {
   person.age ??= 0;
   console.log(person?.age); // 0 and no run-time error
}

printPersonDetails({age: undefined});
```

##Option 4 - Destructuring and Rest defaults
This option is also pretty handy but can take some time to wrap your head around.

###Before
```javascript
var tmp = getSomeRecords();

var first = tmp[0];
var second = tmp[1];

var firstName = first.name;
var firstEmail = first.email !== undefined ? first.email : "nobody@none.tld";

var secondName = second.name;
var secondEmail =
  second.email !== undefined ? second.email : "nobody@none.tld";

function getSomeRecords() {
    return [
      {
        name: "a",
        email: "a@gmail.com",
      },
      {
        name: "b",
        email: "b@gmail.com",
      },
    ];
}
```

###After
```javascript
var [
  {
    name: firstName,
    email: firstEmail = "nobody@none.com"
  },
  {
    name: secondName,
    email: secondEmail = "nobody@none.com"
  }
] = getSomeRecords();

function getSomeRecords() {
  return [
    {
      name: "a"
    },
    {
      name: "b",
      email: "b@gmail.com",
    },
  ];
}
```

The same rest parameter concept can be applicable to function parameters as well.
###Before
```javascript
function printPersonDetails(person) {
   console.log(person.age);
   console.log(person.name);
}

printPersonDetails(undefined); // 💥 💥 Blast!!!
```

###After
```javascript
function printPersonDetails({
   age: age = 0,
   name: name = 'john doe'
}) {
   console.log(age);
   console.log(name);
}

printPersonDetails(undefined); // Works

// OR if you are lazy to repeat properties
function printPersonDetails({
   age = 0,
   name = 'john doe'
}) {
   console.log(age);
   console.log(name);
}

printPersonDetails(undefined); // Works
```

The above technique can also be useful if you have more than 3 parameters in your function and you don't like remembering the sequence of them (I don't). This feature is known as named-parameters.

##Option 5 - Use Elvis(?) operator
I hate this option but I will still list it.

```javascript
function printPersonDetails(person) {
   console.log(person?.age); // undefined and no run-time error
}

printPersonDetails(undefined);
```

But what if person is not undefined and you tried to access a property inside age but age turns out to be undefined/null?

##Option 5.1 Use Elvis(?) operator AND Non-Null Assertions (TypeScript 3.9 onwards only)
```javascript
function printPersonDetails(person) {
   console.log(person?.age!.unit); // undefined and no run-time error
// OR
console.log((person?.age).unit); // undefined and no run-time error
}

printPersonDetails({ age: undefined });
```

The *(...)* or **!** provide the non-null assertions

These techniques are the ones that needs to be followed to avoid embarrassing production run-time errors on your console. 

I have a small YouTube channel named [EverydayJavaScript](https://youtube.com/EverydayJavaScript). Please do subscribe to the channel if you liked this post.

Happy error-free coding!