Declarative Optional.Js

Muthukumaran Navaneethakrishnan
2 min readJan 2, 2022

--

A Javascript library to write concise functional code. Combined with features of Java Optional & Promise chaining

When working on code, There is always possibility to end up with adding more conditionals , null checks ,promises and end up with more subtle duplications.

These subtle duplications was hard to identify , even if we found it , it was hard to eliminate , by applying abstraction.

if functional programming concepts applied effectively by piping multiple expressions or functions, These subtle duplications expose itself and If we could spend some time, we might even able to apply some abstraction on top of it for eliminating these and code might appear compact.

This library supports expression/function composition with single element, promises via map ,filter & flatmap

Features

  • Lazily evaluated
  • Merging multiple Optionals
  • Convert to Stream
  • Chaining sync & async functions/expressions
  • Most of the Java Optional Features

Installation

npm install declarative-optional

Import

// Common JS
const {Optional} = require( "declarative-optional");
//ES6
import
{Optional} from "declarative-optional";

Usecases

Increment a number which may be null or undefined

//Increment a Number , which may be null
Optional.of(input)
.map(val=>val+1)
.get()

All the expressions will be evaluated only after you specified get()

Increment a Number by 5, Only if its divisable by 5

//Increment a Number by 5, Only if its dividable by 5
Optional.of(input)
.filter(val=>val % 5 == 0)
.map(val=>val+5)
.get()

For Asynchronous functions use toAsync() to gather result as Promise<Optional>

Asynchronous Usecases

Validate User Input, Connect to external system and Redirect to a page

Imperative Code

function getFromUserService({username, password}) {
return new Promise((function (resolve) {
resolve({name: "user", isAdmin: true})
}))
}
async function login({username, password}) { if (null == username || null == password) {
throw new Error("Cannot be Null")
}
const result = await getFromUserService(username, password)
if (result.isAdmin) {
redirectTo("adminPage")
} else {
redirectTo("userPage")
}
}

With Declarative Optional

async function login({username, password}) {    const page = await Optional.of({username: user, password: pass})
.filter(({username, password}) => (null != username && null != password))
.map(getFromUserService)
.map(result => result.isAdmin ? "adminPage" : "userPage")
.toAsync();
page.ifPresentOrElse(redirectTo, () => {
throw new Error("Cannot be Null")
})
}

Fetch Todos ,If completed , then display title or else return empty string

Imperative Code

const rawResults = await fetch('https://jsonplaceholder.typicode.com/todos/' + item);
const response = await rawResults.json();
if (response.completed) {
return response.title
} else {
return null
}

With Declarative Optional

return await Optional.of('https://jsonplaceholder.typicode.com/todos/' + item)
.map(fetch)
.map(response => response.json())
.filter(response => response.completed == true)
.map(response => response.title)
.getAsync();

Conclusion

Often Chaining of expressions/functions helps us to keep the code clean , testable , reasonate easily.

This library attempts to do it in a simple manner.

The code is battle tested. Documentation is in progress.

Links

--

--

Muthukumaran Navaneethakrishnan
Muthukumaran Navaneethakrishnan

Written by Muthukumaran Navaneethakrishnan

Software Engineer works on Java, Javascript & Clojure

No responses yet