The library that will conquer the ‘null’-able world
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
orundefined
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 functionsts-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.