Overview
better-result provides type utilities to extract success and error types from Result instances. These utilities are essential when working with complex Result types or building generic functions.
InferOk
Extracts the success value type from a Result type.
The Result type to extract from
The success value type T from Result<T, E>
Type Definition
type InferOk < R > = R extends Ok < infer T , unknown > ? T : never ;
How It Works
InferOk uses a distributive conditional type to extract the success type:
For Ok<A, X> | Ok<B, Y>, returns A | B
For Result<number, Error>, returns number
For non-Result types, returns never
Usage Examples
Basic Usage
Union Types
Generic Functions
With Generator Composition
import { Result , InferOk } from "better-result" ;
type UserResult = Result <{ id : string ; name : string }, Error >;
type User = InferOk < UserResult >;
// User = { id: string; name: string }
InferOk is distributive, meaning it distributes over union types. This is particularly useful when working with multiple Result types in generator compositions.
InferErr
Extracts the error value type from a Result type.
The Result type to extract from
The error value type E from Result<T, E>
Type Definition
type InferErr < R > = R extends Err < unknown , infer E > ? E : never ;
How It Works
InferErr uses a distributive conditional type to extract the error type:
For Err<X, A> | Err<Y, B>, returns A | B
For Result<string, NotFoundError>, returns NotFoundError
For non-Result types, returns never
Usage Examples
Basic Usage
Error Handler
Extracting Generator Errors
Error Normalization
import { Result , InferErr } from "better-result" ;
class ValidationError extends Error {}
class NetworkError extends Error {}
type ApiResult = Result < string , ValidationError | NetworkError >;
type Errors = InferErr < ApiResult >;
// Errors = ValidationError | NetworkError
Both InferOk and InferErr work seamlessly with Result.gen to automatically extract union types from all yielded Results.
Common Patterns
Type-Safe Result Handlers
import { Result , InferOk , InferErr } from "better-result" ;
type Handler < R extends Result < unknown , unknown >> = {
onSuccess : ( value : InferOk < R >) => void ;
onError : ( error : InferErr < R >) => void ;
};
function handle < R extends Result < unknown , unknown >>(
result : R ,
handler : Handler < R >
) : void {
result . match ({
ok: handler . onSuccess ,
err: handler . onError ,
});
}
const result : Result < number , string > = Result . ok ( 42 );
handle ( result , {
onSuccess : ( n ) => console . log ( n * 2 ), // n: number
onError : ( e ) => console . error ( e . toUpperCase ()), // e: string
});
import { Result , InferOk , InferErr } from "better-result" ;
// Define workflow
const fetchUserWorkflow = ( id : string ) =>
Result . gen ( function* () {
const user = yield * getUser ( id ); // Result<User, NotFoundError>
const posts = yield * getPosts ( user . id ); // Result<Post[], DbError>
const profile = yield * getProfile ( user . id ); // Result<Profile, ApiError>
return Result . ok ({ user , posts , profile });
});
// Extract types automatically
type WorkflowResult = ReturnType < typeof fetchUserWorkflow >;
type SuccessData = InferOk < Awaited < WorkflowResult >>;
// SuccessData = { user: User, posts: Post[], profile: Profile }
type AllErrors = InferErr < Awaited < WorkflowResult >>;
// AllErrors = NotFoundError | DbError | ApiError
import { Result , InferOk } from "better-result" ;
function mapSuccess < R extends Result < unknown , unknown >, U >(
result : R ,
fn : ( value : InferOk < R >) => U
) : Result < U , InferErr < R >> {
return result . map ( fn );
}
const numResult = Result . ok ( 42 );
const doubled = mapSuccess ( numResult , ( n ) => n * 2 );
// doubled: Result<number, never>
See Also