@fkws/klonk-result
v0.0.3
Published
A Proxy-based Result type for TypeScript.
Maintainers
Readme
klonk-result
A Proxy-based Result type for TypeScript.
This library implements the Result pattern using ES6 Proxies. It allows property access and method calls to be forwarded directly to the wrapped value. If the result is a failure, these operations are intercepted and the error is propagated.
klonk-result powers the type-safe railway-oriented design of Klonk and Klonkworks.
Implementation Details
The Result<T> type is a union of Ok<T> and Err<T>. A Proxy intercepts operations on the object.
- Ok State: Operations not belonging to the Result API are forwarded to the underlying value
T. - Err State: Accessing members of
Treturns a function that returns the existingErr. This allows chaining to continue without throwing, propagating the initial error.
Installation
bun add @fkws/klonk-result
npm install @fkws/klonk-resultUsage
Basic Wrapper
Create Result objects with a success or failure state.
import { Result } from '@fkws/klonk-result';
function divide(a: number, b: number): Result<number> {
if (b === 0) {
return new Result({ success: false, error: new Error("Division by zero") });
}
return new Result({ success: true, data: a / b });
}
const val = divide(10, 2);
if (val.isOk()) {
console.log("Result:", val.unwrap()); // 5
} else {
console.error(val.error);
}Method Forwarding
Methods can be chained directly on the Result object. The chain executes if the result is successful. If an error occurs at any point, subsequent calls return the error without execution.
class User {
constructor(public name: string) {}
updateName(newName: string): Result<User> {
if (!newName) return new Result({ success: false, error: new Error("Invalid name") });
return new Result({ success: true, data: new User(newName) });
}
save(): Result<void> {
// Database logic
return new Result({ success: true, data: undefined });
}
}
const userResult = new Result({ success: true, data: new User("Alice") });
// The chain continues until an error occurs or the chain ends
const pipeline = userResult
.updateName("Bob")
.updateName("") // Returns Err("Invalid name")
.save(); // Not executed; pipeline remains Err("Invalid name")
if (pipeline.isErr()) {
console.log("Pipeline failed:", pipeline.error.message);
}Primitive Values
Primitives are boxed (e.g., string to String) to allow method access. Methods returning primitives exit the Result wrapper.
const strResult = new Result({ success: true, data: "hello world" });
// .toUpperCase() returns a string, not Result<string>
const upper = strResult.toUpperCase();
console.log(upper); // "HELLO WORLD"API
The following members take precedence over the wrapped value.
success(boolean): Indicates if the result is successful.isOk(): Type guard for the Ok state.isErr(): Type guard for the Err state.unwrap(): ReturnsTif successful; throwsErrorif failed.error(Err only): TheErrorobject.throw()(Err only): Throws the contained error.
License
Mozilla Public License Version 2.0
