@firtoz/maybe-error 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/MaybeError.ts +120 -0
package/package.json
CHANGED
package/src/MaybeError.ts
CHANGED
|
@@ -1,8 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type-safe error handling utilities using discriminated unions
|
|
3
|
+
*
|
|
4
|
+
* This module provides a Result-like pattern for handling operations that may fail,
|
|
5
|
+
* inspired by Rust's Result type and functional programming error handling patterns.
|
|
6
|
+
* Compatible with TypeScript 5.0+ for optimal type inference.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Basic usage
|
|
11
|
+
* const result = success(42);
|
|
12
|
+
* const error = fail("Something went wrong");
|
|
13
|
+
*
|
|
14
|
+
* // Type-safe error handling
|
|
15
|
+
* function divide(a: number, b: number): MaybeError<number> {
|
|
16
|
+
* if (b === 0) return fail("Division by zero");
|
|
17
|
+
* return success(a / b);
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* const result = divide(10, 2);
|
|
21
|
+
* if (result.success) {
|
|
22
|
+
* console.log(result.result); // 5
|
|
23
|
+
* } else {
|
|
24
|
+
* console.error(result.error); // "Division by zero"
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Represents a failed operation with an error value.
|
|
31
|
+
*
|
|
32
|
+
* @template TError - The type of the error value (defaults to string)
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const error: DefiniteError<string> = { success: false, error: "Not found" };
|
|
36
|
+
* const customError: DefiniteError<{code: number, message: string}> = {
|
|
37
|
+
* success: false,
|
|
38
|
+
* error: { code: 404, message: "Resource not found" }
|
|
39
|
+
* };
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
1
42
|
export type DefiniteError<TError = string> = {
|
|
2
43
|
success: false;
|
|
3
44
|
error: TError;
|
|
4
45
|
};
|
|
5
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Represents a successful operation with an optional result value.
|
|
49
|
+
*
|
|
50
|
+
* Uses conditional types to make the result field optional when T is undefined,
|
|
51
|
+
* but required when T has a concrete type.
|
|
52
|
+
*
|
|
53
|
+
* @template T - The type of the success value (defaults to undefined)
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const voidSuccess: DefiniteSuccess = { success: true };
|
|
57
|
+
* const valueSuccess: DefiniteSuccess<number> = { success: true, result: 42 };
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
6
60
|
export type DefiniteSuccess<T = undefined> = {
|
|
7
61
|
success: true;
|
|
8
62
|
} & (T extends undefined
|
|
@@ -13,10 +67,47 @@ export type DefiniteSuccess<T = undefined> = {
|
|
|
13
67
|
result: T;
|
|
14
68
|
});
|
|
15
69
|
|
|
70
|
+
/**
|
|
71
|
+
* A discriminated union representing either a successful result or an error.
|
|
72
|
+
*
|
|
73
|
+
* This is the main type for operations that may fail. The `success` field
|
|
74
|
+
* acts as a discriminant, allowing TypeScript to narrow the type in conditionals.
|
|
75
|
+
*
|
|
76
|
+
* @template T - The type of the success value (defaults to undefined)
|
|
77
|
+
* @template TError - The type of the error value (defaults to string)
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* function fetchUser(id: string): MaybeError<User, ApiError> {
|
|
81
|
+
* // Implementation that returns either success(user) or fail(apiError)
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* const result = fetchUser("123");
|
|
85
|
+
* if (result.success) {
|
|
86
|
+
* // TypeScript knows result.result is User
|
|
87
|
+
* console.log(result.result.name);
|
|
88
|
+
* } else {
|
|
89
|
+
* // TypeScript knows result.error is ApiError
|
|
90
|
+
* console.error(result.error.message);
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
16
94
|
export type MaybeError<T = undefined, TError = string> =
|
|
17
95
|
| DefiniteSuccess<T>
|
|
18
96
|
| DefiniteError<TError>;
|
|
19
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Utility type to extract the success value type from a MaybeError type.
|
|
100
|
+
*
|
|
101
|
+
* Useful for type manipulation when you need to work with the success type
|
|
102
|
+
* without the error handling wrapper.
|
|
103
|
+
*
|
|
104
|
+
* @template T - A MaybeError type
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* type UserResult = MaybeError<User, string>;
|
|
108
|
+
* type UserType = AssumeSuccess<UserResult>; // User
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
20
111
|
export type AssumeSuccess<T extends MaybeError<unknown>> = Exclude<
|
|
21
112
|
T,
|
|
22
113
|
undefined
|
|
@@ -24,6 +115,22 @@ export type AssumeSuccess<T extends MaybeError<unknown>> = Exclude<
|
|
|
24
115
|
? U
|
|
25
116
|
: never;
|
|
26
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Creates a successful result with an optional value.
|
|
120
|
+
*
|
|
121
|
+
* Uses function overloading to provide different signatures based on whether
|
|
122
|
+
* a value is provided or not.
|
|
123
|
+
*
|
|
124
|
+
* @template T - The type of the success value
|
|
125
|
+
* @param params - The success value (optional for void operations)
|
|
126
|
+
* @returns A DefiniteSuccess instance
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const voidResult = success(); // DefiniteSuccess<undefined>
|
|
130
|
+
* const valueResult = success(42); // DefiniteSuccess<number>
|
|
131
|
+
* const stringResult = success("hello"); // DefiniteSuccess<string>
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
27
134
|
export const success = <T = undefined>(
|
|
28
135
|
...params: T extends undefined ? [] : [T]
|
|
29
136
|
): DefiniteSuccess<T> => {
|
|
@@ -37,6 +144,19 @@ export const success = <T = undefined>(
|
|
|
37
144
|
} as unknown as DefiniteSuccess<T>;
|
|
38
145
|
};
|
|
39
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Creates a failed result with an error value.
|
|
149
|
+
*
|
|
150
|
+
* @template TError - The type of the error value
|
|
151
|
+
* @param error - The error value
|
|
152
|
+
* @returns A DefiniteError instance
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const stringError = fail("Something went wrong");
|
|
156
|
+
* const objectError = fail({ code: 500, message: "Internal server error" });
|
|
157
|
+
* const customError = fail(new Error("Custom error"));
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
40
160
|
export const fail = <TError = string>(error: TError): DefiniteError<TError> => {
|
|
41
161
|
return {
|
|
42
162
|
success: false,
|