Optional (null-safe) in javascript
Tags: javascript, optional, webdev, node
Published: 2018-05-23 15:19:27

---
title: Optional (null-safe) in javascript
published: true
description: A simple implementation of an optional API for javascript
tags: javascript, optional, webdev, nodejs
---

Yesterday I ran into [this](https://stackoverflow.com/questions/50452219/how-to-return-blank-string-if-object-is-undefined-in-angularjs-forms) StackOverflow question and it got me thinking about `null`/`undefined` handling in javascript. 

## A short background

**What is `undefined`?** `undefined` is a primitive value that is given to variables that have only been declared, non-existent properties or function arguments

**What is `null`?** `null` is another primitive value that represents the absence of value.

So what happens when we do the following

```javascript

let obj;

console.log(obj.someProp);

```

We get the following error

> TypeError: Cannot read property 'someProp' of undefined

And the same happens with `null`


## null-checking

So, how can we avoid that? Well, lucky for us in javascript we have `short-circuit` evaluation, meaning that in order to avoid our previous `TypeError` we could write the following.


```javascript

let obj;

console.log(obj && obj.someProp); // Prints undefined

```

But what if we want to go deeper, something like `obj.prop1.prop2.prop3`? We would end doing lots of checks, like:


```javascript

console.log( obj && obj.prop1 && obj.prop1.prop2 && obj.prop1.prop2.prop3 );

```

Seems obnoxious, doesn't it?

And what if we wanted to print a default value if there was an `undefined` or `null` in that chain? Then it would be an even larger expression:


```javascript

const evaluation = obj && obj.prop1 && obj.prop1.prop2 && obj.prop1.prop2.prop3;

console.log( evaluation != null ? evaluation : "SomeDefaultValue" );

```

## How do other languages do it?

This issue is not exclusive of javascript, it is present in most programming languages, so let's see how to do null-checking in some of them.


#### Java

In java we have the `Optional` API:

```java

SomeClass object;

Optional.ofNullable(object)
    .map(obj -> obj.prop1)
    .map(obj -> obj.prop2)
    .map(obj -> obj.prop3)
    .orElse("SomeDefaultValue");

```

#### Kotlin

In kotlin (another JVM language) there are the *elvis* (`?:`) and *safe-call* (`?.`) operators.


```kotlin

val object: SomeClass?

object?.prop1?.prop2?.prop3 ?: "SomeDefaultValue";

```

#### C&#35;

Finally, in c# we also have the *null-condition* (`?.`) and *null-coalescing* (`??`) operators.

```csharp

SomeClass object;

object?.prop1?.prop2?.prop3 ?? "SomeDefaultValue";

```

## JS Options

So after seeing all this, I was wondering, *isn't there a way to avoid writing that much in javascript?*, so I started experimenting with regex to write a function that'd allow me to access an object property safely.

```javascript

function optionalAccess(obj, path, def) {
  const propNames = path.replace(/\]|\)/, "").split(/\.|\[|\(/);

  return propNames.reduce((acc, prop) => acc[prop] || def, obj);
}

const obj = {
  items: [{ hello: "Hello" }]
};

console.log(optionalAccess(obj, "items[0].hello", "def")); // Prints Hello
console.log(optionalAccess(obj, "items[0].he", "def")); // Prints def

```

And after that, I found about `lodash._get`, which has the same signature:

`_.get(object, path, [defaultValue])`

But to be honest I'm not that much a fan of string paths so I started searching a way to avoid them, then I came with a solution using proxies:


```javascript

// Here is where the magic happens
function optional(obj, evalFunc, def) {
  
  // Our proxy handler
  const handler = {
    // Intercept all property access
    get: function(target, prop, receiver) {
      const res = Reflect.get(...arguments);

      // If our response is an object then wrap it in a proxy else just return
      return typeof res === "object" ? proxify(res) : res != null ? res : def;
    }
  };

  const proxify = target => {
    return new Proxy(target, handler);
  };

  // Call function with our proxified object
  return evalFunc(proxify(obj, handler));
}

const obj = {
  items: [{ hello: "Hello" }]
};

console.log(optional(obj, target => target.items[0].hello, "def")); // => Hello
console.log(optional(obj, target => target.items[0].hell, { a: 1 })); // => { a: 1 }

```

## The future

Currently, there is a [TC39 proposal](https://github.com/tc39/proposal-optional-chaining) that will allow us to do the following:

```javascript

obj?.arrayProp?[0]?.someProp?.someFunc?.();

```

Looks pretty neat right? However, this proposal is still in stage 1, which means it will probably take a while before we can see this is js. Nonetheless, there is a babel [plugin](https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-optional-chaining) that allows us to use that syntax.

## Finale

`null` has been and will be around for a while and I bet is one of the most hated concepts in programming, however, there are ways to procure *null-safety*. Here I've posted my two cents, let me know what you think or if you have any other alternatives.




p.s.: Here is a little pretty [gist](https://gist.github.com/pichardoJ/76e3bb814b86d5a8860f9a2956e827ad)