@tevari/helpers
Version:
Collection of various small helpers for javascript and typescript based projects
251 lines (213 loc) • 7.56 kB
text/typescript
import {
Function1,
Predicate,
Consumer,
Supplier,
Function2,
Procedure,
} from "./functions";
import { NoSuchElementException } from "./exceptions";
/**
* A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
* Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).
*
* This is a value-based class; use of identity-sensitive operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.
*/
export class Optional<T> {
private constructor(private value?: T) {}
/**
* Returns an empty Optional instance.
*/
public static empty<T>() {
return new Optional<T>();
}
/**
* Returns an Optional with the specified present non-null value.
*
* @param value The value to fill the Optional with.
* @returns an Optional with the given value.
*/
public static filled<T>(value: T) {
return new Optional<T>(value);
}
/**
* Returns an Optional with the specified present value if non-null, otherwise returns an empty Optional.
*
* @param value The value to fill the Optional with.
* @returns an Optional with the given value if non-null, an empty Optional otherwise.
*/
public static of<T>(value?: T) {
if (value === undefined || value === null) return Optional.empty<T>();
return new Optional<T>(value!!);
}
/**
* Indicates whether some other object is "equal to" this Optional.
*
* @param other Object to compare this optional value with.
* @param comparator The predicate used to compare the values.
* @returns `true`if the two values are equal, `false` otherwise.
*/
public equals(other: T, comparator?: Function2<T, T, boolean>): boolean {
if (this.isEmpty()) return false;
if (comparator) return comparator(this.value!!, other);
return this.value === other;
}
/**
* Casts this Optional to the given type.
*
* @returns a new optional typed as the given type.
*/
public as<U>(): Optional<U> {
return Optional.of<U>(this.value as U);
}
/**
* Sets the given value. If a value is already present, this method replaces it.
*
* @param value The value to set.
*/
public set(value: T) {
this.value = value;
return this;
}
/**
* If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException.
*
* @returns the value if present, throws NoSuchElementException otherwise.
*/
public get() {
if (this.isEmpty())
throw new NoSuchElementException(
"[Optional] You are trying to get an empty value."
);
return this.value!!;
}
/**
* If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.
*
* @param predicate To filter the value with if present.
* @returns a filled Optional if a value is present and it matches the given predicate, and emlpty Optional otherwise.
*/
public filter(predicate: Predicate<T>): Optional<T> {
if (this.isEmpty() || !predicate(this.value!!)) return Optional.empty();
return Optional.of(this.value);
}
/**
* If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result.
*
* @param mapper The mapper function.
* @returns the result Optional if a value is present, an empty Optional otherwise.
*/
public map<U>(mapper: Function1<T, U>): Optional<U> {
if (this.isEmpty()) return Optional.empty();
return Optional.of(mapper(this.value!!));
}
/**
* If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional.
*
* @param mapper The mapper function.
* @returns the result Optional if a value is present, an empty Optional otherwise.
*/
public flatMap<U>(mapper: Function1<T, Optional<U>>): Optional<U> {
if (this.isEmpty()) return Optional.empty();
return mapper(this.value!!);
}
/**
* Tests whether this optional is empty.
*
* @returns `true` if there is no present value, otherwise `false`.
*/
public isEmpty(): boolean {
if (this.value === undefined || this.value === null) return true;
return false;
}
/**
* Tests whether a value is present.
*
* @returns `true` if there is a value present, otherwise `false`.
*/
public isPresent(): boolean {
if (this.isEmpty()) return false;
return true;
}
/**
* If a value is present, invoke the specified consumer with the value, otherwise do nothing.
*
* @param consumer The consumer to invoke if a value is present.
* @returns itself for chaining purposes.
*/
public ifPresent(consumer: Consumer<T>): Optional<T> {
if (this.isEmpty()) return this;
consumer(this.value!!);
return this;
}
/**
* Return the value if present, otherwise return other.
*
* @param other The default value to return if this Optional is empty.
* @returns the value if present, otherwise `other`.
*/
public orElse(other: T): T {
if (this.isEmpty()) return other;
return this.value!!;
}
/**
* If the optional is empty, invokes the specified supplier, otherwise do nothing.
*
* @param other The default value to return if this Optional is empty.
* @returns itself for chaining purposes.
*/
public orElseInvoke(procedure: Procedure): Optional<T> {
if (this.isPresent()) return this;
procedure();
return this;
}
/**
* Return the value if present, otherwise return `undefined`.
*
* @returns the value if present, otherwise `undefined`.
*/
public orUndefined(): T | undefined {
if (this.isEmpty()) return undefined;
return this.value!!;
}
/**
* Return the value if present, otherwise return `null`.
*
* @returns the value if present, otherwise `null`.
*/
public orNull(): T | null {
if (this.isEmpty()) return null;
return this.value!!;
}
/**
* Return the value if present, otherwise invoke other and return the result of that invocation.
*
* @param supplier The supplier to invoke when the value is not present.
* @returns either the value if present, the result of the given supplier otherwise.
*/
public orElseGet(supplier: Supplier<T>): T {
if (this.isEmpty()) return supplier();
return this.value!!;
}
/**
* Return the contained value, if present, otherwise throw an exception to be created by the provided supplier.
*
* @param exceptionSupplier
* @returns
*/
public orElseThrow<U extends Error>(exceptionSupplier: Supplier<U>): T {
if (this.isEmpty()) throw exceptionSupplier();
return this.value!!;
}
/**
* If a value is present, apply the provided resolver function to it, and if the result is non-null, return an Optional describing the result.
*
* @param resolver The resolver function.
* @param other The value to return if the Optional is empty.
* @returns the result Optional if a value is present, the given `other` parameter otherwise.
*/
public resolve<U>(resolver: Function1<T, U>, other: U): U {
if (this.isEmpty()) return other;
return resolver(this.value!!);
}
}