#Asserting Results
When you've exhausted all possible errors through operations like orElse or andThen, you can use assertSuccess and assertFailure to assert the Result type at compile time. Combined with unwrap and unwrapError, this enables safe value extraction.
#Asserting Success with assertSuccess
The assertSuccess function asserts that a Result is a Success. This function requires the error type to be never, ensuring at compile time that the Result is guaranteed to be a Success:
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<number, never> result : import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, never> = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
const const success: Result.Success<number> success = import Result Result .const assertSuccess: <Result.Result<number, never>>(result: Result.Result<number, never>) => Result.Success<number>Asserts that a
Result
or
ResultAsync
is a
Success
and returns it.
This function requires that the result's error type is never, meaning the result is
guaranteed to be a
Success
at the type level.
If the result is a
Failure
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the error type.@paramresult - The Result or ResultAsync to assert as a Success.
The error type must be never.@returnsThe Success result or a Promise of Success result.@throws{Error} If the result is a Failure at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@exampleType-safe usage after narrowing error type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.succeed(42);
const value = Result.pipe(
getResult(),
Result.orElse(() => Result.succeed(0)), // Error type becomes never
Result.assertSuccess, // Type-safe: error type is now never
Result.unwrap(), // Safe unwrap after assertion
);
@seeunwrap - Use with assertSuccess to safely unwrap success values.@categoryAssertions assertSuccess (const result: Result.Result<number, never> result );
// success: { type: 'Success', value: 42 }#When Error Type is Not never
If the error type is not never, TypeScript will raise a compilation error:
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<number, string> result : import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, string> = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
// ❌ TypeScript error: error type is string, not never
const const success: Promise<Result.Success<any>> success = import Result Result .const assertSuccess: <Result.ResultMaybeAsync<any, never>>(result: Result.ResultMaybeAsync<any, never>) => Promise<Result.Success<any>>Asserts that a
Result
or
ResultAsync
is a
Success
and returns it.
This function requires that the result's error type is never, meaning the result is
guaranteed to be a
Success
at the type level.
If the result is a
Failure
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the error type.@paramresult - The Result or ResultAsync to assert as a Success.
The error type must be never.@returnsThe Success result or a Promise of Success result.@throws{Error} If the result is a Failure at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@exampleType-safe usage after narrowing error type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.succeed(42);
const value = Result.pipe(
getResult(),
Result.orElse(() => Result.succeed(0)), // Error type becomes never
Result.assertSuccess, // Type-safe: error type is now never
Result.unwrap(), // Safe unwrap after assertion
);
@seeunwrap - Use with assertSuccess to safely unwrap success values.@categoryAssertions assertSuccess (result);Argument of type 'Result<number, string>' is not assignable to parameter of type 'ResultMaybeAsync<any, never>'.
Type 'Failure<string>' is not assignable to type 'ResultMaybeAsync<any, never>'.
Type 'Failure<string>' is not assignable to type 'Failure<never> | Promise<Result<any, never>>'.
Type 'Failure<string>' is not assignable to type 'Failure<never>'.
Type 'string' is not assignable to type 'never'.#Making Error Type never with orElse
Use orElse to handle all errors and narrow the error type to never:
import { import Result Result } from '@praha/byethrow';
declare const const getResult: () => Result.Result<number, "NotFound" | "NetworkError"> getResult : () => import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, 'NotFound' | 'NetworkError'>;
const const result: Result.Success<number> result = import Result Result .const pipe: <Result.Result<number, "NotFound" | "NetworkError">, Result.Result<number, never>, Result.Success<number>>(a: Result.Result<number, "NotFound" | "NetworkError">, ab: (a: Result.Result<number, "NotFound" | "NetworkError">) => Result.Result<number, never>, bc: (b: Result.Result<number, never>) => Result.Success<number>) => Result.Success<number> (+25 overloads) pipe (
const getResult: () => Result.Result<number, "NotFound" | "NetworkError"> getResult (),
import Result Result .const orElse: <Result.Result<number, "NotFound" | "NetworkError">, Result.Result<0, never>>(fn: (a: "NotFound" | "NetworkError") => Result.Result<0, never>) => (result: Result.Result<number, "NotFound" | "NetworkError">) => Result.Result<number, never> (+1 overload) orElse ((error: "NotFound" | "NetworkError" error ) => {
// Handle all errors and return a fallback value
return import Result Result .const succeed: <0>(value: 0) => Result.Result<0, never> (+1 overload) succeed (0);
}),
// Error type is now never
import Result Result .const assertSuccess: <R extends Result.ResultMaybeAsync<any, never>>(result: R) => true extends HasPromise<R> ? Promise<Result.Success<Result.InferSuccess<R>>> : Result.Success<Result.InferSuccess<R>>Asserts that a
Result
or
ResultAsync
is a
Success
and returns it.
This function requires that the result's error type is never, meaning the result is
guaranteed to be a
Success
at the type level.
If the result is a
Failure
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the error type.@paramresult - The Result or ResultAsync to assert as a Success.
The error type must be never.@returnsThe Success result or a Promise of Success result.@throws{Error} If the result is a Failure at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@exampleType-safe usage after narrowing error type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.succeed(42);
const value = Result.pipe(
getResult(),
Result.orElse(() => Result.succeed(0)), // Error type becomes never
Result.assertSuccess, // Type-safe: error type is now never
Result.unwrap(), // Safe unwrap after assertion
);
@seeunwrap - Use with assertSuccess to safely unwrap success values.@categoryAssertions assertSuccess ,
);
// result: { type: 'Success', value: number }#Asserting Failure with assertFailure
The assertFailure function is the opposite—it asserts that a Result is a Failure. This function requires the success type to be never:
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<never, string> result : import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <never, string> = import Result Result .const fail: <"error">(error: "error") => Result.Result<never, "error"> (+1 overload) fail ('error');
const const failure: Result.Failure<string> failure = import Result Result .const assertFailure: <Result.Result<never, string>>(result: Result.Result<never, string>) => Result.Failure<string>Asserts that a
Result
or
ResultAsync
is a
Failure
and returns it.
This function requires that the result's success type is never, meaning the result is
guaranteed to be a
Failure
at the type level.
If the result is a
Success
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the success type.@paramresult - The Result or ResultAsync to assert as a Failure.
The success type must be never.@returnsThe Failure result or a Promise of Failure result.@throws{Error} If the result is a Success at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@exampleType-safe usage after narrowing success type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.fail('error');
const value = Result.pipe(
getResult(),
Result.andThen(() => Result.fail('die')), // Success type becomes never
Result.assertFailure, // Type-safe: success type is now never
Result.unwrapError(), // Safe unwrap after assertion
);
@seeunwrapError - Use with assertFailure to safely unwrap error values.@categoryAssertions assertFailure (const result: Result.Result<never, string> result );
// failure: { type: 'Failure', error: 'error' }#When Success Type is Not never
If the success type is not never, TypeScript will raise a compilation error:
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<number, string> result : import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, string> = import Result Result .const fail: <"error">(error: "error") => Result.Result<never, "error"> (+1 overload) fail ('error');
// ❌ TypeScript error: success type is number, not never
const const failure: Promise<Result.Failure<any>> failure = import Result Result .const assertFailure: <Result.ResultMaybeAsync<never, any>>(result: Result.ResultMaybeAsync<never, any>) => Promise<Result.Failure<any>>Asserts that a
Result
or
ResultAsync
is a
Failure
and returns it.
This function requires that the result's success type is never, meaning the result is
guaranteed to be a
Failure
at the type level.
If the result is a
Success
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the success type.@paramresult - The Result or ResultAsync to assert as a Failure.
The success type must be never.@returnsThe Failure result or a Promise of Failure result.@throws{Error} If the result is a Success at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@exampleType-safe usage after narrowing success type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.fail('error');
const value = Result.pipe(
getResult(),
Result.andThen(() => Result.fail('die')), // Success type becomes never
Result.assertFailure, // Type-safe: success type is now never
Result.unwrapError(), // Safe unwrap after assertion
);
@seeunwrapError - Use with assertFailure to safely unwrap error values.@categoryAssertions assertFailure (result);Argument of type 'Result<number, string>' is not assignable to parameter of type 'ResultMaybeAsync<never, any>'.
Type 'Success<number>' is not assignable to type 'ResultMaybeAsync<never, any>'.
Type 'Success<number>' is not assignable to type 'Success<never> | Promise<Result<never, any>>'.
Type 'Success<number>' is not assignable to type 'Success<never>'.
Type 'number' is not assignable to type 'never'.#Making Success Type never with andThen
Use andThen to make all paths fail and narrow the success type to never:
import { import Result Result } from '@praha/byethrow';
declare const const getResult: () => Result.Result<number, string> getResult : () => import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, string>;
const const result: Result.Failure<string> result = import Result Result .const pipe: <Result.Result<number, string>, Result.Result<never, string>, Result.Failure<string>>(a: Result.Result<number, string>, ab: (a: Result.Result<number, string>) => Result.Result<never, string>, bc: (b: Result.Result<never, string>) => Result.Failure<string>) => Result.Failure<string> (+25 overloads) pipe (
const getResult: () => Result.Result<number, string> getResult (),
import Result Result .const andThen: <Result.Result<number, string>, Result.Result<never, "converted error">>(fn: (a: number) => Result.Result<never, "converted error">) => (result: Result.Result<number, string>) => Result.Result<never, string> (+1 overload) andThen (() => {
// All paths lead to failure
return import Result Result .const fail: <"converted error">(error: "converted error") => Result.Result<never, "converted error"> (+1 overload) fail ('converted error');
}),
// Success type is now never
import Result Result .const assertFailure: <R extends Result.ResultMaybeAsync<never, any>>(result: R) => true extends HasPromise<R> ? Promise<Result.Failure<Result.InferFailure<R>>> : Result.Failure<Result.InferFailure<R>>Asserts that a
Result
or
ResultAsync
is a
Failure
and returns it.
This function requires that the result's success type is never, meaning the result is
guaranteed to be a
Failure
at the type level.
If the result is a
Success
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the success type.@paramresult - The Result or ResultAsync to assert as a Failure.
The success type must be never.@returnsThe Failure result or a Promise of Failure result.@throws{Error} If the result is a Success at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@exampleType-safe usage after narrowing success type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.fail('error');
const value = Result.pipe(
getResult(),
Result.andThen(() => Result.fail('die')), // Success type becomes never
Result.assertFailure, // Type-safe: success type is now never
Result.unwrapError(), // Safe unwrap after assertion
);
@seeunwrapError - Use with assertFailure to safely unwrap error values.@categoryAssertions assertFailure ,
);
// result: { type: 'Failure', error: string }#Safe Unwrapping with assertSuccess + unwrap
By combining assertSuccess with unwrap, you can safely extract values from a Result. Since the error type is never after the assertion, unwrap is guaranteed not to throw:
import { import Result Result } from '@praha/byethrow';
declare const const getResult: () => Result.Result<number, "NotFound" | "NetworkError"> getResult : () => import Result Result .type Result<T, E> = Result.Success<T> | Result.Failure<E>A union type representing either a success or a failure.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const doSomething = (): Result.Result<number, string> => {
return Math.random() > 0.5
? { type: 'Success', value: 10 }
: { type: 'Failure', error: 'Oops' };
};
@categoryCore Types Result <number, 'NotFound' | 'NetworkError'>;
const const value: number value = import Result Result .const pipe: <Result.Result<number, "NotFound" | "NetworkError">, Result.Result<number, never>, Result.Success<number>, number>(a: Result.Result<number, "NotFound" | "NetworkError">, ab: (a: Result.Result<number, "NotFound" | "NetworkError">) => Result.Result<number, never>, bc: (b: Result.Result<number, never>) => Result.Success<number>, cd: (c: Result.Success<number>) => number) => number (+25 overloads) pipe (
const getResult: () => Result.Result<number, "NotFound" | "NetworkError"> getResult (),
import Result Result .const orElse: <Result.Result<number, "NotFound" | "NetworkError">, Result.Result<0, never>>(fn: (a: "NotFound" | "NetworkError") => Result.Result<0, never>) => (result: Result.Result<number, "NotFound" | "NetworkError">) => Result.Result<number, never> (+1 overload) orElse (() => import Result Result .const succeed: <0>(value: 0) => Result.Result<0, never> (+1 overload) succeed (0)), // Handle all errors
import Result Result .const assertSuccess: <R extends Result.ResultMaybeAsync<any, never>>(result: R) => true extends HasPromise<R> ? Promise<Result.Success<Result.InferSuccess<R>>> : Result.Success<Result.InferSuccess<R>>Asserts that a
Result
or
ResultAsync
is a
Success
and returns it.
This function requires that the result's error type is never, meaning the result is
guaranteed to be a
Success
at the type level.
If the result is a
Failure
at runtime, throws an error.
@function@typeParamR - The result type that extends ResultMaybeAsync with never as the error type.@paramresult - The Result or ResultAsync to assert as a Success.
The error type must be never.@returnsThe Success result or a Promise of Success result.@throws{Error} If the result is a Failure at runtime.@exampleimport { Result } from '@praha/byethrow';
const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@exampleType-safe usage after narrowing error type
import { Result } from '@praha/byethrow';
const getResult = (): Result.Result<number, string> => Result.succeed(42);
const value = Result.pipe(
getResult(),
Result.orElse(() => Result.succeed(0)), // Error type becomes never
Result.assertSuccess, // Type-safe: error type is now never
Result.unwrap(), // Safe unwrap after assertion
);
@seeunwrap - Use with assertSuccess to safely unwrap success values.@categoryAssertions assertSuccess , // Error type is now never
import Result Result .const unwrap: <Result.Success<number>>() => (result: Result.Success<number>) => number (+3 overloads) unwrap (), // Safe: guaranteed not to throw
);
// value: numberThis pattern is particularly useful at application boundaries where you want to ensure type safety while extracting the final value.
#Difference from Runtime Type Guards
It's important to understand the difference between assertSuccess/assertFailure and isSuccess/isFailure:
| Function | Purpose | Throws on Mismatch? |
|---|---|---|
isSuccess | Runtime check, returns boolean | No |
isFailure | Runtime check, returns boolean | No |
assertSuccess | Compile-time assertion (requires never) | Yes (if type is wrong) |
assertFailure | Compile-time assertion (requires never) | Yes (if type is wrong) |
isSuccess/isFailure: Use when you need to branch based on the Result type at runtimeassertSuccess/assertFailure: Use when you've already ensured the Result type at compile time and want to assert it
#References
| Function | Purpose |
|---|---|
| assertSuccess(result) | Assert that a Result is Success (requires error type to be never) |
| assertFailure(result) | Assert that a Result is Failure (requires success type to be never) |
