optionals-js v3.0.1
OptionalJS 🎁
A robust and elegant Optional implementation for JavaScript, inspired by Java's Optional class. This package helps you handle null pointer exceptions gracefully and write more maintainable code by providing a container object that may or may not contain a non-null value.
Why OptionalJS? 🤔
The Null Pointer Exception Problem
JavaScript developers often encounter issues with null or undefined values:
// Dangerous code
const user = getUser(); // might be null
const address = user.address; // 💥 TypeError: Cannot read property 'address' of null
const city = address.city;
This leads to the infamous:
TypeError: Cannot read property 'x' of null
The Optional Solution
OptionalJS provides a safe way to handle potentially null values:
const user = Optional.ofNullable(getUser())
.map(u => u.address)
.map(a => a.city)
.orElse("Unknown City");
Installation 📦
npm install optionals-js
Usage 💡
Basic Usage
const Optional = require('optionals-js');
// Creating Optionals
const present = Optional.of("hello"); // Contains non-null value
const nullable = Optional.ofNullable(null); // Empty optional
const empty = Optional.empty(); // Empty optional
// Checking values
console.log(present.isPresent()); // true
console.log(nullable.isEmpty()); // true
// Safe access
const value = present.get(); // Returns "hello"
const safe = nullable.orElse("default"); // Returns "default"
Chaining Operations
const result = Optional.ofNullable(user)
.map(user => user.profile)
.map(profile => profile.settings)
.map(settings => settings.theme)
.orElse("default-theme");
Conditional Operations
Optional.ofNullable(user)
.filter(user => user.age >= 18)
.ifPresent(user => console.log("Adult user:", user))
.ifEmpty(() => console.log("No adult user found"));
Error Handling
try {
const value = Optional.empty()
.orElseThrow(() => new Error("Value required!"));
} catch (error) {
console.log(error.message); // "Value required!"
}
Practical Examples
User Authentication
const getUsername = (user) => {
return Optional.ofNullable(user)
.map(u => u.profile)
.map(p => p.username)
.orElse("anonymous");
};
// Usage
const user = {
profile: {
username: "john_doe"
}
};
console.log(getUsername(user)); // "john_doe"
console.log(getUsername(null)); // "anonymous"
Configuration Management
const getConfig = (path) => {
return Optional.ofNullable(process.env)
.map(env => env[path])
.filter(value => value.length > 0)
.orElseGet(() => loadDefaultConfig(path));
};
Form Validation
const validateEmail = (formData) => {
return Optional.ofNullable(formData.email)
.map(email => email.trim())
.filter(email => email.includes("@"))
.map(email => ({ isValid: true, email }))
.orElse({ isValid: false, error: "Invalid email" });
};
API Reference 📚
Static Methods
Optional.of(value)
Creates an Optional with a non-null value. Throws if value is null/undefined.
const opt = Optional.of("hello");
Optional.ofNullable(value)
Creates an Optional that may contain a null value.
const opt = Optional.ofNullable(possiblyNullValue);
Optional.empty()
Creates an empty Optional.
const opt = Optional.empty();
Instance Methods
get()
const value = Optional.of("hello").get(); // "hello"
isPresent()
const hasValue = Optional.of("hello").isPresent(); // true
isEmpty()
const isEmpty = Optional.empty().isEmpty(); // true
ifPresent(consumer)
Optional.of("hello")
.ifPresent(value => console.log(value));
ifEmpty(action)
Optional.empty()
.ifEmpty(() => console.log("No value"));
map(mapper)
const mapped = Optional.of("hello")
.map(str => str.toUpperCase()); // Optional containing "HELLO"
filter(predicate)
const filtered = Optional.of(5)
.filter(num => num > 3); // Optional containing 5
orElse(other)
const value = Optional.empty()
.orElse("default"); // "default"
orElseGet(supplier)
const value = Optional.empty()
.orElseGet(() => computeDefault()); // Result of computeDefault()
orElseThrow(exceptionSupplier)
const value = Optional.empty()
.orElseThrow(() => new Error("Required!")); // Throws Error
Comparison with Java Optional 🔄
OptionalJS is inspired by Java's Optional class but with some JavaScript-specific enhancements:
- More fluent API with method chaining
- Additional
ifEmpty
method for empty case handling - JavaScript-specific null/undefined handling
- No checked exceptions
- More functional programming friendly
Best Practices 🌟
- Use Optional as a return type, not as a parameter type
- Don't overuse - Optional is for exceptional cases, not for all nullable values
- Chain operations when possible instead of nesting
- Use
ifPresent
/ifEmpty
for side effects - Prefer
orElse
/orElseGet
overget()
Links 🔗
Contributing 🤝
Contributions are welcome! Please feel free to submit a Pull Request.
License 📄
This project is licensed under the MIT License - see the LICENSE file for details.
Credits 💝
Inspired by Java's Optional class and functional programming patterns.
Made with ❤️ by Abhijit Verma