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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.fail('error');
const failure = Result.assertFailure(result);
// failure: { type: 'Failure', error: 'error' }
@example

Type-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.@example
import { 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.@example
import { Result } from '@praha/byethrow';

const result = Result.succeed(42);
const success = Result.assertSuccess(result);
// success: { type: 'Success', value: 42 }
@example

Type-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: number

This 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:

FunctionPurposeThrows on Mismatch?
isSuccessRuntime check, returns booleanNo
isFailureRuntime check, returns booleanNo
assertSuccessCompile-time assertion (requires never)Yes (if type is wrong)
assertFailureCompile-time assertion (requires never)Yes (if type is wrong)
  • isSuccess/isFailure: Use when you need to branch based on the Result type at runtime
  • assertSuccess/assertFailure: Use when you've already ensured the Result type at compile time and want to assert it

References

FunctionPurpose
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)