89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
/**
|
|
* Result type for handling success and error cases in a type-safe way.
|
|
*
|
|
* This class MUST ONLY be used within use cases (AsyncUseCase and UseCase implementations).
|
|
* It is NOT allowed to be used in domain entities, services, repositories, presenters, or any other layer.
|
|
* Use cases are the only place where business logic decisions that can fail should be made,
|
|
* and Result provides a way to handle those failures without throwing exceptions.
|
|
*
|
|
* @template T - The type of the success value
|
|
* @template E - The type of the error value, typically ApplicationErrorCode<string>
|
|
*/
|
|
export class Result<T, E = Error> {
|
|
public constructor(
|
|
private readonly _value?: T,
|
|
private readonly _error?: E,
|
|
private readonly _isSuccess: boolean = true
|
|
) {}
|
|
|
|
static ok<T, E = Error>(value: T): Result<T, E> {
|
|
return new Result<T, E>(value, undefined, true);
|
|
}
|
|
|
|
static err<T, E = Error>(error: E): Result<T, E> {
|
|
return new Result<T, E>(undefined, error, false);
|
|
}
|
|
|
|
isOk(): boolean {
|
|
return this._isSuccess;
|
|
}
|
|
|
|
isErr(): boolean {
|
|
return !this._isSuccess;
|
|
}
|
|
|
|
unwrap(): T {
|
|
if (!this._isSuccess) {
|
|
throw new Error('Called unwrap on an error result');
|
|
}
|
|
return this._value!;
|
|
}
|
|
|
|
unwrapOr(defaultValue: T): T {
|
|
return this._isSuccess ? this._value! : defaultValue;
|
|
}
|
|
|
|
unwrapErr(): E {
|
|
if (this._isSuccess) {
|
|
throw new Error('Called unwrapErr on a success result');
|
|
}
|
|
return this._error!;
|
|
}
|
|
|
|
map<U>(fn: (value: T) => U): Result<U, E> {
|
|
if (this._isSuccess) {
|
|
return Result.ok(fn(this._value!));
|
|
}
|
|
return Result.err(this._error!);
|
|
}
|
|
|
|
mapErr<F>(fn: (error: E) => F): Result<T, F> {
|
|
if (!this._isSuccess) {
|
|
return Result.err(fn(this._error!));
|
|
}
|
|
return Result.ok(this._value!);
|
|
}
|
|
|
|
andThen<U>(fn: (value: T) => Result<U, E>): Result<U, E> {
|
|
if (this._isSuccess) {
|
|
return fn(this._value!);
|
|
}
|
|
return Result.err(this._error!);
|
|
}
|
|
|
|
/**
|
|
* Direct access to the value (for testing convenience).
|
|
* Prefer using unwrap() in production code.
|
|
*/
|
|
get value(): T | undefined {
|
|
return this._value;
|
|
}
|
|
|
|
/**
|
|
* Direct access to the error (for testing convenience).
|
|
* Prefer using unwrapErr() in production code.
|
|
*/
|
|
get error(): E | undefined {
|
|
return this._error;
|
|
}
|
|
} |