Declarative Optional.Js
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.