Optional gives the power to differentiate between the absence of a value and the null or undefined reference
The Optional class is an utility class that provides a way to handle potentially null or undefined values in a more concise and expressive manner. It allows wrapping a value in an Optional object, which can then be used to perform various operations on the value, such as checking if it is present, retrieving it, applying transformations, and handling empty values.
Overall, this simple yet powerful class helps create code thatβs, simply put, more readable and less error-prone than its procedural counterpart.
Global Functions
The best way to wrap and starting using optional is through the global utility functions.
optionalOf
Wraps a value that might be undefined or null in an Optional container.
constresult1=optionalOf("Hello");if (result1.isPresent()) {console.log(result1.get()); // Prints: Hello}constresult2=optionalOf(null);if (result2.isEmpty()) {console.log("Value is not present"); // Prints: Value is not present}constresult3=optionalOf(undefined);console.log(result3.orElse("Default")); // Prints: Defaultconstresult4=awaitoptionalOf(user).orElseThrow(() =>newHttpError(409,"User doesn't exist")).map(user => {return {...user, userData, }; }).runAsync(user =>this.userRepository.save(user));console.log(result4); // Prints: saved user content
allPresent
Checks if all the elements in an array of Optional objects have a non-empty value.
Checks if none of the Optional objects in the array are present.
constoptionalsWithValues= [Optional.of("Hello"),Optional.of("World")];constareNonePresent1=Optional.nonePresent(optionalsWithValues);// areNonePresent1: false (both Optionals have values)constoptionalsWithEmptyValues= [Optional.empty(),Optional.empty()];constareNonePresent2=Optional.nonePresent(optionalsWithEmptyValues);// areNonePresent2: true (both Optionals are empty)constmixedOptionals= [Optional.of("Hello"),Optional.empty()];constareNonePresent3=Optional.nonePresent(mixedOptionals);// areNonePresent3: false (at least one Optional has a value)
coalesce
Returns the first non-empty optional from a list of optionals, or an empty optional if all optionals are empty.
The of method creates a new Optional object with a specified value. It wraps the value, allowing for more concise and expressive code when dealing with potentially null or undefined values.
Retrieve the value of the Optional object if it is present, or throw an error if the Optional object is empty.
constoptionalValue=Optional.of("Hello");constvalue=optionalValue.orElseThrow(() =>newError("Value is not present"));console.log(value); // Output: "Hello"constemptyOptional=Optional.empty();emptyOptional.orElseThrow(() =>newError("Value is not present")); // Throws an error
map
Transform the value inside the Optional object using a provided mapper function. It returns a new Optional object with the mapped value. If the original Optional object is empty, it throws an error.
constoptional=Optional.of(5); // Create an Optional object with a value of 5constmappedOptional=optional.map(value => value *2); // Map the value to its doubleconsole.log(mappedOptional.get()); // Output: 10constemptyOptional=Optional.empty(); // Create an empty Optional objectconstdefaultValue=0;const mappedEmptyOptional = emptyOptional.map(value => value * 2, defaultValue); // Map the value to its double or use the default value if empty
console.log(mappedEmptyOptional.get()); // Output: 0
flatMap
Apply a mapper function to the value inside the Optional object and return a new Optional object with the mapped value. If the original Optional object is empty, it throws an error.
Chaining asynchronous operations on an optional value. It takes a mapper function that returns a promise of an Optional object. If the current optional value is present, it applies the mapper function and returns the result as an Optional object. If the current optional value is empty, it returns an empty Optional object.
Filter the value inside the Optional object based on a given predicate function. It returns a new Optional object containing the filtered value if the original Optional object is present, or an empty Optional object if the original Optional object is not present.
constoptional=Optional.of([1,2,3,4,5]); // Create an Optional object with an array valueconstfilteredOptional=optional.filter(value => value >3); // Filter the array to keep only values greater than 3console.log(filteredOptional.get()); // Output: [4, 5]constemptyOptional=Optional.empty(); // Create an empty Optional objectconstfilteredEmptyOptional=emptyOptional.filter(value => value >3); // Filter the empty Optional objectconsole.log(filteredEmptyOptional.isEmpty()); // Output: true
isEmpty
Checks if the value inside the Optional object is empty or not.
constoptionalValue=Optional.of("Hello"); // Create an Optional object with a non-empty valueconsole.log(optionalValue.isEmpty()); // Output: falseconstemptyOptional=Optional.empty(); // Create an Optional object with an empty valueconsole.log(emptyOptional.isEmpty()); // Output: true
ifEmpty
Executes a specified action if the value inside the Optional object is empty.
constoptional=Optional.of(null);optional.ifEmpty(() =>console.log("Value is empty")); // Output: "Value is empty"
ifEmptyThrow
Throws an error if the value inside the Optional object is empty, otherwise it returns the Optional object.
constoptional=Optional.of("value");optional.ifEmptyThrow(() =>newError("Value is empty")); // Returns the optional objectconstemptyOptional=Optional.empty();emptyOptional.ifEmptyThrow(() =>newError("Value is empty")); // Throws an error
ifEmptyGet
Returns the value inside the Optional object if it is not empty, otherwise it returns a default value provided by a callback function.
Checks if a given predicate function returns true for every value inside the Optional object.
constoptional=Optional.of([1,2,3]);constresult=optional.every(value => value >0);console.log(result); // true
some
Checks if a given predicate function returns true for at least one value inside the Optional object.
constoptional=Optional.of([1,2,3]);constresult=optional.some(value => value >0);console.log(result); // true
match
Checks if the value inside the Optional object matches a given condition.
constoptional=Optional.of(5);constisEven=optional.match(value => value %2===0);console.log(isEven); // true
run
Allows you to execute a callback function on the value stored in the Optional object and return a new Optional object with the result.
constoptional=Optional.of(5); // Create an Optional object with a value of 5const newOptional = optional.run(value => value * 2); // Execute the callback function on the value and create a new Optional object with the result
console.log(newOptional.get()); // Output: 10
runAsync
Allows you to asynchronously execute a callback function on the value contained within the Optional object.
constoptional=Optional.of(5); // Create an Optional object with a value of 5constasyncCallback=async (value:number) => {// Perform some asynchronous operation on the valueconstresult=awaitsomeAsyncFunction(value);return result;};constresultPromise=optional.runAsync(asyncCallback); // Execute the async callback on the valueresultPromise.then(result => {console.log(result); // Output the result of the asynchronous operation}).catch(error => {console.error(error); // Handle any errors that occurred during the asynchronous operation});
else
Used to provide an alternative value or action when the optional value is empty.
Used to execute a callback function asynchronously if the optional value is empty. It returns a promise that resolves to the result of the callback function.