nullable v2.0.0
nullable
plain implementation of Maybe (Optional, Nullable) monad
example usage & motivation
Can you spot the error?
const userA = {name: 'Basha', pet: null}
const userB = {name: 'Cheyenne', pet: {name: 'Adonis', species: 'cat'}}
const users = [userA, userB]
users.forEach(user => {
console.log(`Hi ${user.name} and ${user.pet.name} the ${user.pet.species}!`)
})
// * this will give us a null reference error!
// TypeError: Cannot read property 'name' of nullInstead, we could enclose the assumption that the user has a pet using Nullable:
const Nullable = require('nullable')
users.forEach(user => {
console.log(`Hi ${user.name}${
Nullable(user.pet)
.map({name, species} => ` and ${name} the ${species}`)
.orDefault('')
}!`)
})
// => 'Hi Basha!'
// => 'Hi Cheyenne and Adonis the cat!'We can do some other things with Nullables, too:
const foo = Nullable({a: {b: c: 5}, bar: () => 23})
console.log(
foo.get('a').get('b').get('c').map((x) => x + 5)
.orDefault('??')
)
// => 10
foo.get('c').orDefault('??')
// => '??'
foo.call('bar').orDefault('??')
// => 23Depending on your background, you may also know this as Maybe or Option or Nullable Structs.
Nullable works similar to Promises, in that it is a container datatype which wraps a value which may be null, or else have a value.
The idea is that all operations and transformations that are done on this value should only happen once and if the value is not null - and if it is, we can avoid explicit and error-prone manual null checking.
If you're sick of seeing errors like Uncaught TypeError: Cannot read property 'name' of null in your programs, I encourage you to use Nullables.
You may use Nullables as a functional utility library, like you might lodash, or you can model your objects with nullables so you may call methods directly.
The general pattern is:
1. enclose the part of your program that depends on certain data always being there
2. do any operations or transformations using Nullable#map(). Calling this always returns another Nullalbe, like how Promise#then() always returns another Promise.
3. When you're done, get at the value by calling orDefault(val), providing a default value.
This follows the same general pattern as Promises: wrap - map - unwrap
api
Nullable : (T) => Nullable<T>
Constructor, may be called with or without new
also aliased as Nullable.of and Nullable#of (both static and instance methods)
Nullable<T>#map : (fn: (T)=>T2) => Nullable<T2>
Map a function fn to the value if available. Returns a Nullable of the return type of fn. Analogous to Array#map
Nullable<T>#call : (String, ...Any) => Nullable<T2>
Call a method on the underlying value if available. Returns a Nullable of the return type of the method. Additional parameters are optional and work like Function#call
Nullable<T>#orDefault : (Any) => T | Any
Returns the underlying value if available, or the default argument specified.
this method is also aliased as Nullable<T>#orElse, which may feel more intuitive to you
additional exposed properties
It is preferable to interact with Nullable via the map, call, and orDefault methods, but the following properties are exposed. Using them, and especially changing them, can make your programs more error-prone and harder to understand and reason about. Caveat utilitor.
Nullable<T>#value : T?
Access the underlying value, if available. May be null or undefined
Nullable<T>#hasValue : Boolean
Nullable<T>#isNull : Boolean
Nullable<T>#isUndefined : Boolean
installation
$ npm install nullablerunning the tests
From package root:
$ npm install
$ npm testcontributors
- jason@denizac.org
license
ISC. (c) MMXVI jason@denizac.org. See LICENSE.md