KrustyKrab: Rust-Inspired Utilities for JavaScript/TypeScript
KrustyKrab provides idiomatic implementations of Rust's `Option` and `Result` types, along with several utility functions inspired by Rust's standard library, for JavaScript and TypeScript projects. It aims to enhance error handling and null safety by introducing concepts like explicit handling of present/absent values and success/failure states. The current stable version is 1.1.0. As a relatively new library focused on bringing Rust paradigms to TypeScript, its release cadence is likely driven by feature additions and improvements rather than a fixed schedule. Key differentiators include its faithful adaptation of `Option` and `Result` with methods like `unwrap`, `unwrapOr`, `map`, and `andThen`, as well as practical utilities such as `getResult` for converting Promises, `toOption` for nullable conversions, and `tryCatch` for wrapping synchronous operations in `Result` types. This approach encourages more robust, explicit, and functional error management compared to traditional try-catch blocks and null checks.
Common errors
-
Error: Called unwrap on a None value
cause Attempted to call `.unwrap()` on an `Option` instance that was actually `None`.fixEnsure the `Option` is `Some` before calling `unwrap()` using `isSome()`, or use safer alternatives like `unwrapOr(defaultValue)`, `map()`, or `andThen()`. -
Error: Called unwrap on an Err value
cause Attempted to call `.unwrap()` on a `Result` instance that was actually `Err`.fixCheck if the `Result` is `Ok` using `isOk()` before calling `unwrap()`, or handle the error gracefully using `unwrapOr(defaultValue)`, `mapErr()`, or `andThen()`.
Warnings
- gotcha The `unwrap()` method on `Option` and `Result` types will throw a runtime error if called on a `None` or `Err` instance respectively. This behavior mimics Rust's `panic!` and is intended for situations where the value is *guaranteed* to be present. Use `unwrapOr()`, `map()`, `andThen()`, or `match` (if implemented) for safer access.
- gotcha KrustyKrab is designed with TypeScript in mind, and its full benefits, particularly type inference and strict null checks, are best utilized in a TypeScript project. While it can be used in plain JavaScript, you'll lose compile-time type safety for `Option` and `Result` operations, potentially leading to more runtime errors that TypeScript would catch.
Install
-
npm install krustykrab -
yarn add krustykrab -
pnpm add krustykrab
Imports
- Option and Result types
const { Some, None } = require('krustykrab');import { Some, None, Ok, Err } from 'krustykrab'; - unwrap, unwrapOr, unwrapOrElse
import unwrap from 'krustykrab/unwrap';
import { unwrap, unwrapOr, unwrapOrElse } from 'krustykrab'; - getResult, toOption, tryCatch
import * as KrustyKrab from 'krustykrab';
import { getResult, toOption, tryCatch } from 'krustykrab';
Quickstart
import { Some, None, Ok, Err, unwrap, getResult, toOption, tryCatch } from 'krustykrab';
// Demonstrating Option type for null safety
const maybeValue = Some("Hello, KrustyKrab!");
console.log(maybeValue.isSome()); // true
console.log(maybeValue.unwrapOr("Default")); // "Hello, KrustyKrab!"
const noValue = None<string>();
console.log(noValue.isNone()); // true
console.log(noValue.unwrapOr("Default Value")); // "Default Value"
// Demonstrating Result type for error handling
const successfulResult = Ok(42);
console.log(successfulResult.isOk()); // true
console.log(successfulResult.unwrap()); // 42
const failedResult = Err("Something went wrong!");
console.log(failedResult.isErr()); // true
console.log(failedResult.unwrapErr()); // "Something went wrong!"
// Utility: unwrap - panics on null/undefined
const fooOrNull: string | null = 'foo';
const guaranteedFoo = unwrap(fooOrNull); // 'foo'
// unwrap(null); // This would throw an error at runtime
// Utility: getResult - converting Promises
async function fetchData() {
const dataPromise = Promise.resolve({ id: 1, name: 'Spongebob' });
const result = await getResult(dataPromise);
if (result.isOk()) {
console.log('Fetched data:', result.unwrap());
} else {
console.error('Failed to fetch:', result.unwrapErr());
}
}
fetchData();
// Utility: tryCatch - wrapping synchronous operations
const jsonString = '{"item":"crabby patty"}';
const parsedResult = tryCatch(() => JSON.parse(jsonString));
if (parsedResult.isOk()) {
console.log('Parsed JSON:', parsedResult.unwrap());
} else {
console.error('JSON parse error:', parsedResult.unwrapErr());
}
const invalidJsonString = '{invalid json}';
const invalidParsedResult = tryCatch(() => JSON.parse(invalidJsonString));
console.log('Invalid JSON parse was an error:', invalidParsedResult.isErr()); // true