import { Narrow } from "./ts-helpers/types.js"; /** * A `Success` represents a successful computation that returns a value of type `T`. * * `E` in `Success` is the type of the error that would have been returned in case of failure. * It's present only to allow type safety of the `isFailure` method. * * @sealed * @privateRemarks DO NOT EXPORT, see type export later on * @typeParam T - the success value type */ declare class Success { readonly value: T; /** @internal */ constructor(value: T); isSuccess(): this is Success; isFailure(): this is Failure; unwrap(): T; } /** * A `Success` represents a successful computation that returns a value of type `T`. * * `T` in `Failure` is the type of the value that would have been returned in case of success. * It's present only to allow type safety of the `isSuccess` method. * * @sealed * @privateRemarks DO NOT EXPORT, see type export later on * @typeParam E - the failure error type */ declare class Failure { readonly error: E; /** @internal */ constructor(error: E); isSuccess(): this is Success; isFailure(): this is Failure; unwrap(): never; } export type { Success, Failure }; /** * An `IEquatableError` is an error that can be compared by name. * */ export interface IEquatableError> { name: P; } /** * A `Result` type represents either `Success` or `Failure`. * * **TL;DR** * * `Result` is a minimalist implementation of a value that can be a "success" or a "failure". * It borrows from what done in other modern languages (i.e. Rust, Kotlin, Swift, etc.). * * The Lens SDK adopts this pattern in order to: * - be explicit about the known failure scenarios of a task, * - provide a way for consumers to perform exhaustive error handling, * - makes control flow easier to reason about. * * @remarks * * You might be familiar with the `Either` type from functional programming. The `Result` type * could be seen as a more specific version of `Either` where the left side is reserved for * success scenarios and the right side is reserved for known failure scenarios. * * Think of failure scenarios as alternative outcomes of a given task that although not the "happy path", * are still legitimate results for the task within the boundary of a correct usage of the SDK. * * In promoting exhaustive error handling, the Lens SDK makes it easier to evolve your code * when a new error case is added or a case is removed. * For example after a Lens SDK upgrade you can simply run the TS compiler to figure out where you * need to handle the new error cases, or even better, it guides you to remove obsolescent code * where an error case is no longer possible. This is virtually impossible with a `try/catch` approach. * * Thrown exceptions are historically difficult to trace. They require implicit knowledge * of the implementation details of the code that might throw exceptions. This might go several * layers down and leads to tight coupling between modules. * * The Lens SDK still throws exceptions where the error is not a "normal execution scenario". * These are considered real "exceptional circumstances" and not alternative outcomes and it's up to the consumer to `try/catch` them. * * An example of errors that are thrown by the SDK is {@link InvariantError}. They are often thrown as result of a misuse of the SDK. * By throwing them we want to fail fast so the consumer can fix the issue as soon as possible. * Specifically for `InvariantError`, there is no need to code defensively against these errors. Just rectify the coding issue and move on. * * @example * Control flow * ```ts * const result: Result = doSomething(); * * if (result.isFailure()) { * // because of the `isFailure` check above, TS knows that `result` is a `Failure` here * console.log(result.error); // result.error gets narrowed to `RangeError` * * return; // early return * } * * // because of the `isFailure` check above and the early return, TS knows that `result` is a `Success` here * console.log(result.value); // result.value gets narrowed to `number` * ``` * * @example * Exhaustive error handling * * Given a result type like the following: * * ```ts * const result: Result = doSomething(); * ``` * You can use a function with a `switch` statement to perform exhaustive error handling: * ```ts * function format(failure: Failure): string { * switch (failure.error.name) { * case 'PendingSigningError': * return 'Please sign the transaction'; * break; * case 'WalletConnectionError': * return 'Please connect your wallet and try again'; * break; * } * // any code after the switch statement is unreachable * } * ``` * The example above assumes `allowUnreachableCode: false` in your `tsconfig.json`. * * An even more robust way to perform exhaustive error handling with a `switch` is to use the `never` type: see {@link https://www.typescriptlang.org/docs/handbook/2/narrowing.html#exhaustiveness-checking | exhaustiveness checking}. * * @see https://wiki.c2.com/?AvoidExceptionsWheneverPossible * @see https://developer.apple.com/documentation/swift/result * @see https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/ * @see https://the-guild.dev/blog/graphql-error-handling-with-fp#monads-to-the-rescue * * @typeParam T - the success value type * @typeParam E - the failure error type */ export type Result = Success | Failure; /** * A `PromiseResult` is a convenience type alias that represents either a {@link Result} in the context of asynchronous tasks. * * @typeParam T - the success value type * @typeParam E - the failure error type */ export type PromiseResult = Promise>; /** * @internal */ export declare function success(): Success; export declare function success(value: T): Success; /** * @internal */ export declare const failure: >(error: E) => Failure; /** * Ensures the `Result` is a `Success`. */ export declare function assertSuccess(result: Result): asserts result is Success; /** * Ensures the `Result` is a `Failure`. */ export declare function assertFailure(result: Result): asserts result is Failure;