Implementation:Helicone Helicone Result Type
| Knowledge Sources | |
|---|---|
| Domains | Error Handling, Type System, Core Utilities |
| Last Updated | 2026-02-14 06:32 GMT |
Overview
A Rust-inspired discriminated union Result<T, K> type that provides type-safe error handling across the entire Helicone codebase, replacing exception-based error propagation with explicit success/error values.
Description
The result module defines the foundational Result<T, K> type used throughout Helicone for safe error handling. The type is a discriminated union of ResultSuccess<T> (with data: T and error: null) and ResultError<K> (with data: null and error: K). The error type K defaults to string.
The module provides a comprehensive set of utility functions:
- Constructors:
ok(data)anderr(error)for creating result values - Type guards:
isError(result)andisSuccess(result)for narrowing types - Unwrappers:
unwrap(result),unwrapAsync(result), andunwrapList(results)for extracting values with exception on error - Transformers:
resultMap(result, fn),map(result, fn), andpromiseResultMap(result, fn)for applying functions to successful results - Combiners:
resultsAll(results)for combining multiple results into a tuple, failing on the first error
Usage
Use this type as the return type for any function that can fail, instead of throwing exceptions. It is the standard error-handling pattern across all Helicone packages and services, particularly in managers and controllers within the Jawn backend.
Code Reference
Source Location
- Repository: Helicone
- File: packages/common/result/index.ts
Signature
export interface ResultError<K> { data: null; error: K; }
export interface ResultSuccess<T> { data: T; error: null; }
export type Result<T, K = string> = ResultSuccess<T> | ResultError<K>;
// Constructors
export function ok<T, K = string>(data: T): Result<T, K>
export function err<T, K = string>(error: K): Result<T, K>
// Type guards
export function isError<T, K>(result: Result<T, K>): result is ResultError<K>
export function isSuccess<T, K>(result: Result<T, K>): result is ResultSuccess<T>
// Unwrappers
export function unwrap<T, K>(result: Result<T, K>): T
export function unwrapAsync<T, K>(result: Promise<Result<T, K>>): Promise<T>
export function unwrapList<T, K>(results: Result<T, K>[]): T[]
// Transformers
export function resultMap<T, K, Z>(result: Result<T, K>, f: (data: T) => Z): Result<Z, K>
export function map<T, K, L>(result: Result<T, K>, mapFn: (data: T) => L): Result<L, K>
export function promiseResultMap<T, K, Z>(
result: Result<T, K>, f: (data: T) => Promise<Z>
): Promise<Result<Z, K>>
// Combiners
export function resultsAll<T extends Result<any, any>[]>(
results: [...T]
): Result<AllSuccessTuple<T>, UnwrapError<T[number]>>
Import
import { Result, ok, err, isError, isSuccess, unwrap, resultMap, resultsAll } from "@helicone/common/result";
I/O Contract
| Function | Parameters | Returns | Description |
|---|---|---|---|
ok
|
data: T
|
Result<T, K>
|
Creates a success result |
err
|
error: K
|
Result<T, K>
|
Creates an error result |
isError
|
result: Result<T, K>
|
boolean (type guard)
|
Checks if result is an error |
isSuccess
|
result: Result<T, K>
|
boolean (type guard)
|
Checks if result is a success |
unwrap
|
result: Result<T, K>
|
T
|
Extracts value or throws on error |
resultMap
|
result: Result<T, K>, f: (T) => Z
|
Result<Z, K>
|
Transforms the success value |
resultsAll
|
results: Result[]
|
Result<Tuple, Error>
|
Combines results, fails on first error |
Usage Examples
import { Result, ok, err, isError, resultMap, resultsAll } from "@helicone/common/result";
// Returning results from a function
async function fetchUser(id: string): Promise<Result<User, string>> {
const user = await db.users.find(id);
if (!user) {
return err("User not found");
}
return ok(user);
}
// Consuming results
const result = await fetchUser("123");
if (isError(result)) {
console.error(result.error); // "User not found"
return;
}
console.log(result.data.name); // TypeScript knows data is User
// Transforming results
const nameResult = resultMap(result, (user) => user.name);
// Combining multiple results
const [userResult, orgResult] = [await fetchUser("1"), await fetchOrg("2")];
const combined = resultsAll([userResult, orgResult]);
if (isError(combined)) {
return combined; // Propagate the first error
}
const [user, org] = combined.data; // Both values available