The library that will conquer the ‘null’-able world

Dmitry Komarov
4 min readMar 25, 2023

--

Photo by stephan cassara on Unsplash

Introduction

Hi guys! I think many of you reading articles like me: just quickly check the introduction and if find it interesting — continue, otherwise — drop it. I appreciate your time, so, first of all, let me provide you a small recap, in other words — TLDR:

  • Yes, it’s one more ‘optional’ library for JS/TS
  • Yes, I re-invent the wheel
  • But before, I’ve tried to find something similar and all of them had their own dark sides
  • So, I’ve implemented something new the way I’ve wanted
  • And now, I use it every day and I like it

If you reckon, that it would not be useful for you — not a problem, just close this page. But, if you are interested in my experience, I will try to show you how this library helps me in my day-to-day work.

Problem

If you are still here, let’s talk about the problem, what I am trying to solve. All is very simple: the vast majority of JS/TS objects could have null or undefined values. And, in many cases, before the useage, we need to check them like this:

if (some_object) {
// do something useful
}

// or like this

if (some_object !== null && some_object !== undefined) {
// do something useful
}

// or even like this

const another_object = some_object || default_value;

It’s very annoying to write every time such if, ||or && constructions. And I’ve wanted to find the way how to overcome this problem.

Solution

Since I like functional programming style, the solution is very simple and you can find it in many other languages. For example, in Java there is a class Optional for it. So, I’ve just taken it as a base, a starting point, added some useful for me utility functions and ‘voi la’, I’ve created my small but powerful library.

Examples

I think, the best thing I can do here — just to show it in action. Let me provide you only 3 usecases from my daily work:

  • Display an optional field on the page or, even, hide the component based on it:
import * as React from 'react';
import {fromNullable} from 'optional-neo';

type DateFieldProps = {
label: string;
value?: Date;
};

export const DateField_1: React.FC<DateFieldProps> = ({label, value}) => (
<div>
<label>{label}</label>
<div>
{
// Here we create an optional object
// from undefined-able field and display
// it in case of some value,
// otherwiese print '-'
}

{fromNullable(value)
.map(v => v.toString())
.getOrElse('-')
}
</div>
</div>
);

export const DateField_2: React.FC<DateFieldProps> = ({label, value}) =>
// Here we create an optional object
// from undefined-able field and display it
// in case of some value, otherwiese return null
fromNullable(value)
.map(v => (
<div>
<label>{label}</label>
<div>
{v.toString()}
</div>
</div>
))
.getOrNull();
  • When I’d started to use it, I’ve faced with problem of combining several optional objects into single one. The next example demonstrate the solution:
import {group, some} from 'optional-neo';

// Here we create 2 optional objects
// via function 'some'
const firstDateOpt = some(new Date(2023, 1, 1));
const secondDateOpt = some(new Date(2022, 12, 31));

// isDayBefore (boolean) - is the constant,
// which tell us, is 'firstDateOpt' before 'secondDateOpt' or not
// via function 'group'
const isDayBefore = group({
first: firstDateOpt,
second: secondDateOpt,
})
.map(
(first: Date, second: Date) => first.getTime() < second.getTime()
)
.getOrElse(false);
  • In case of real null or undefined object we need to consider some backup, default value. Let me show you, how I deal with it:
import {fromNullable, Optional, some} from 'optional-neo';

// Since it is incorrect Date,
// it will be parsed to NaN.
// We just filter it out and convert to empty Optional
const resolvedMillis: Optional<number> = fromNullable(
Date.parse('date')
).filter(
millis => !isNaN(millis)
);
const nowMillis: Optional<number> = some(Date.UTC());

console.log(
resolvedMillis
.backUp(nowMillis)
.getOrNull()
); // for example, 1679157633434

Comparison with competitors

As I’ve already said, before I’d re-invented the wheel, I’d tried to seek something similar in npmjs.com and found several ones. But they’ve not satisfied me:

  • optional-js — does not have necessary utility functions
  • ts-opt — has too big size (unpacked size is 3.2 MB)
  • optional-typescript — contains a lot of useless for me functions (async, for example. I prefer to have a small and very simple lib and use it for my own async functions as a helper)

Conclusion

So, if you are here, first of all I want to say ‘ Thank you ’. You’ve spent your time for this article and may be you have found it useful. If so — just install it via npm i optional-neo. And for sure, if you want to check its code, welcome to my github.

Once again, thank you for your attention.

--

--

Dmitry Komarov
Dmitry Komarov

No responses yet