Skip to content

Instantly share code, notes, and snippets.

@awendland
Last active February 3, 2016 21:16
Show Gist options
  • Save awendland/7f1e088c192f58cc429f to your computer and use it in GitHub Desktop.
Save awendland/7f1e088c192f58cc429f to your computer and use it in GitHub Desktop.
Basic implementation of handling null/falsy values functionally
/**
* Optional wrapper type for functional handling of nulls/falsy values
*
* @TODO Support chaining of .or()
*/
export class Optional<T> {
constructor(
private _val: T,
private _justNull = false) {}
/**
* Get the raw value wrapped by this Optional
* @return {T} [description]
*/
get val(): T {
return this._val;
}
/**
* Test the first value for truthyness (@see iif) or non-nullness (@see iff).
* If the first value isn't valid, then use the provided other value
* instead.
*
* @param {T | () => T} other An alternative value to use, or, if the
* alternative value is expensive to calculate,
* a function that will yield that alternative
* value instead
* @return {[type]} [description]
*/
or (other: T | (() => T)): T {
if (this._justNull) {
if (this._val !== null && this._val !== undefined) {
return this._val;
}
} else {
if (this._val) {
return this._val;
}
}
// Test if `other` is a function. See http://stackoverflow.com/a/6000016
if (other && other.constructor && other['call'] && other['apply']) {
return (other as () => T)();
} else {
return other as T;
}
}
}
/**
* Return an Optional wrapper that can be used for functional handling of null
* or undefined values. See the Optional class for more details.
*
* @param {T} val A value that can potentially be falsy. If the value is falsy,
* the other value provided in the .or call on the Optional will
* be used instead
* @return {Optional<T>}
*/
export function iif<T>(val: T): Optional<T> {
return new Optional(val);
}
/**
* Return an Optional wrapper that can be used for functional handling of null
* or undefined values. See the Optional class for more details.
*
* @param {T} val A value that can potentially be null. If the value is null,
* the other value provided in the .or call on the Optional will
* be used instead
* @return {Optional<T>}
*/
export function iff<T>(val: T): Optional<T> {
return new Optional(val, true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment