@hulla/control 0.0.0 → 0.0.1
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/dist/cjs/index.d.ts +440 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/es/index.d.mts +440 -0
- package/dist/es/index.mjs +2 -0
- package/dist/es/index.mjs.map +1 -0
- package/package.json +1 -1
@@ -0,0 +1,440 @@
|
|
1
|
+
/**
|
2
|
+
* Base result type with common functionality.
|
3
|
+
*
|
4
|
+
* This type provides the core methods shared between Ok and Err types.
|
5
|
+
* It includes type guards and value access methods that are essential
|
6
|
+
* for the Result pattern implementation.
|
7
|
+
*
|
8
|
+
* @template T - The type of the success value
|
9
|
+
* @template E - The type of the error value
|
10
|
+
*/
|
11
|
+
type BaseResult<T, E> = {
|
12
|
+
/**
|
13
|
+
* Type guard that checks if this result is an Ok value.
|
14
|
+
* @returns true if the result is Ok<T>, false otherwise
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* const result = ok("success")
|
18
|
+
* if (result.isOk()) {
|
19
|
+
* // TypeScript knows result.value exists here
|
20
|
+
* console.log(result.value) // "success"
|
21
|
+
* }
|
22
|
+
*
|
23
|
+
* @example
|
24
|
+
* const result = err(new Error("failed"))
|
25
|
+
* if (!result.isOk()) {
|
26
|
+
* // TypeScript knows this is an Err
|
27
|
+
* console.log(result.error.message) // "failed"
|
28
|
+
* }
|
29
|
+
*/
|
30
|
+
isOk: () => this is Ok<T>;
|
31
|
+
/**
|
32
|
+
* Type guard that checks if this result is an Err value.
|
33
|
+
* @returns true if the result is Err<E>, false otherwise
|
34
|
+
*
|
35
|
+
* @example
|
36
|
+
* const result = err(new Error("failed"))
|
37
|
+
* if (result.isErr()) {
|
38
|
+
* // TypeScript knows result.error exists here
|
39
|
+
* console.log(result.error.message) // "failed"
|
40
|
+
* }
|
41
|
+
*
|
42
|
+
* @example
|
43
|
+
* const result = ok("success")
|
44
|
+
* if (!result.isErr()) {
|
45
|
+
* // TypeScript knows this is an Ok
|
46
|
+
* console.log(result.value) // "success"
|
47
|
+
* }
|
48
|
+
*/
|
49
|
+
isErr: () => this is Err<E>;
|
50
|
+
/**
|
51
|
+
* Unwraps the result to get the raw value.
|
52
|
+
* @returns The contained value (T) if Ok, or the error (E) if Err
|
53
|
+
*
|
54
|
+
* @example
|
55
|
+
* const okResult = ok("success")
|
56
|
+
* console.log(okResult.unwrap()) // "success"
|
57
|
+
*
|
58
|
+
* @example
|
59
|
+
* const errResult = err(new Error("failed"))
|
60
|
+
* console.log(errResult.unwrap()) // Error: failed
|
61
|
+
*/
|
62
|
+
unwrap: () => T | E;
|
63
|
+
};
|
64
|
+
/**
|
65
|
+
* Extended base type for Ok results with success-specific methods.
|
66
|
+
*
|
67
|
+
* This type adds methods specific to handling success values, including
|
68
|
+
* pattern matching and tuple conversion. It handles both synchronous and
|
69
|
+
* asynchronous (Promise) values.
|
70
|
+
*
|
71
|
+
* @template T - The type of the success value
|
72
|
+
*/
|
73
|
+
type OkBaseResult<T> = BaseResult<T, never> & {
|
74
|
+
/**
|
75
|
+
* Pattern matches on the result, transforming the success value.
|
76
|
+
* For Ok results, only the ok function is called.
|
77
|
+
*
|
78
|
+
* @template ROk - The type to transform the success value to
|
79
|
+
* @template RErr - The type that would be returned for errors (never used for Ok)
|
80
|
+
* @param ok - Function to transform the success value
|
81
|
+
* @param _err - Optional function for error case (never called for Ok)
|
82
|
+
* @returns Transformed success value, wrapped in Promise if T is a Promise
|
83
|
+
*
|
84
|
+
* @example
|
85
|
+
* // Synchronous value
|
86
|
+
* const result = ok(5)
|
87
|
+
* const doubled = result.match(
|
88
|
+
* value => value * 2,
|
89
|
+
* () => 0 // never called for Ok
|
90
|
+
* ) // doubled = 10
|
91
|
+
*
|
92
|
+
* @example
|
93
|
+
* // Async value
|
94
|
+
* const result = ok(Promise.resolve(5))
|
95
|
+
* const doubled = await result.match(
|
96
|
+
* async value => value * 2,
|
97
|
+
* () => 0
|
98
|
+
* ) // doubled = 10
|
99
|
+
*/
|
100
|
+
match: <ROk, RErr>(ok: (value: Awaited<T>) => ROk, _err?: (error: never) => RErr) => T extends Promise<any> ? Promise<ROk> : ROk;
|
101
|
+
/**
|
102
|
+
* Converts the result to a tuple of [value, undefined].
|
103
|
+
* This is useful for destructuring and handling both success and error cases uniformly.
|
104
|
+
*
|
105
|
+
* @returns A tuple where the first element is the success value and the second is undefined,
|
106
|
+
* wrapped in Promise if T is a Promise
|
107
|
+
*
|
108
|
+
* @example
|
109
|
+
* // Synchronous value
|
110
|
+
* const result = ok("success")
|
111
|
+
* const [value, error] = result.pair()
|
112
|
+
* console.log(value) // "success"
|
113
|
+
* console.log(error) // undefined
|
114
|
+
*
|
115
|
+
* @example
|
116
|
+
* // Async value
|
117
|
+
* const result = ok(Promise.resolve("success"))
|
118
|
+
* const [value, error] = await result.pair()
|
119
|
+
* console.log(value) // "success"
|
120
|
+
* console.log(error) // undefined
|
121
|
+
*/
|
122
|
+
pair: () => T extends Promise<any> ? Promise<[Awaited<T>, undefined]> : [T, undefined];
|
123
|
+
};
|
124
|
+
/**
|
125
|
+
* Extended base type for Err results with error-specific methods.
|
126
|
+
*
|
127
|
+
* This type adds methods specific to handling error values, including
|
128
|
+
* pattern matching and tuple conversion. It handles both synchronous and
|
129
|
+
* asynchronous (Promise) errors.
|
130
|
+
*
|
131
|
+
* @template E - The type of the error value
|
132
|
+
*/
|
133
|
+
type ErrBaseResult<E> = BaseResult<never, E> & {
|
134
|
+
/**
|
135
|
+
* Pattern matches on the result, transforming the error value.
|
136
|
+
* For Err results, only the err function is called.
|
137
|
+
*
|
138
|
+
* @template ROk - The type that would be returned for success (never used for Err)
|
139
|
+
* @template RErr - The type to transform the error value to
|
140
|
+
* @param _ok - Function for success case (never called for Err)
|
141
|
+
* @param err - Function to transform the error value
|
142
|
+
* @returns Transformed error value, wrapped in Promise if E is a Promise
|
143
|
+
*
|
144
|
+
* @example
|
145
|
+
* // Synchronous error
|
146
|
+
* const result = err(new Error("failed"))
|
147
|
+
* const message = result.match(
|
148
|
+
* () => "", // never called for Err
|
149
|
+
* error => `Error: ${error.message}`
|
150
|
+
* ) // message = "Error: failed"
|
151
|
+
*
|
152
|
+
* @example
|
153
|
+
* // Async error
|
154
|
+
* const result = err(Promise.resolve(new Error("failed")))
|
155
|
+
* const message = await result.match(
|
156
|
+
* () => "",
|
157
|
+
* async error => `Error: ${error.message}`
|
158
|
+
* ) // message = "Error: failed"
|
159
|
+
*/
|
160
|
+
match: <ROk, RErr>(_ok: (value: never) => ROk, err: (error: Awaited<E>) => RErr) => E extends Promise<any> ? Promise<RErr> : RErr;
|
161
|
+
/**
|
162
|
+
* Converts the result to a tuple of [undefined, error].
|
163
|
+
* This is useful for destructuring and handling both success and error cases uniformly.
|
164
|
+
*
|
165
|
+
* @returns A tuple where the first element is undefined and the second is the error value,
|
166
|
+
* wrapped in Promise if E is a Promise
|
167
|
+
*
|
168
|
+
* @example
|
169
|
+
* // Synchronous error
|
170
|
+
* const result = err(new Error("failed"))
|
171
|
+
* const [value, error] = result.pair()
|
172
|
+
* console.log(value) // undefined
|
173
|
+
* console.log(error.message) // "failed"
|
174
|
+
*
|
175
|
+
* @example
|
176
|
+
* // Async error
|
177
|
+
* const result = err(Promise.resolve(new Error("failed")))
|
178
|
+
* const [value, error] = await result.pair()
|
179
|
+
* console.log(value) // undefined
|
180
|
+
* console.log(error.message) // "failed"
|
181
|
+
*/
|
182
|
+
pair: () => E extends Promise<any> ? Promise<[undefined, Awaited<E>]> : [undefined, E];
|
183
|
+
};
|
184
|
+
/**
|
185
|
+
* Helper type to create a tagged variant of a result type.
|
186
|
+
*
|
187
|
+
* This type modifies the tag property of a result type while preserving
|
188
|
+
* all other properties and methods. It's used internally to implement
|
189
|
+
* custom tagging for both Ok and Err types.
|
190
|
+
*
|
191
|
+
* @template T - The base result type to modify
|
192
|
+
* @template Tag - The string literal type for the new tag
|
193
|
+
*
|
194
|
+
* @example
|
195
|
+
* // Tagged Ok result
|
196
|
+
* type SuccessResult = WithTag<Ok<string>, "SUCCESS">
|
197
|
+
* const result: SuccessResult = ok("data", "SUCCESS")
|
198
|
+
* console.log(result.tag) // "SUCCESS"
|
199
|
+
*
|
200
|
+
* @example
|
201
|
+
* // Tagged Err result
|
202
|
+
* type ValidationError = WithTag<Err<Error>, "VALIDATION">
|
203
|
+
* const error: ValidationError = err(new Error("invalid"), "VALIDATION")
|
204
|
+
* console.log(error.tag) // "VALIDATION"
|
205
|
+
*/
|
206
|
+
type WithTag<T, Tag extends string> = Omit<T, 'tag'> & {
|
207
|
+
tag: Tag;
|
208
|
+
};
|
209
|
+
type ResultConfig<T, E extends Error, TagError extends string, TagOk extends string> = Partial<{
|
210
|
+
isError: (value: T | E) => value is E;
|
211
|
+
tagError: TagError;
|
212
|
+
tagOk: TagOk;
|
213
|
+
}>;
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Success type that preserves tag information.
|
217
|
+
*
|
218
|
+
* Represents a successful computation result with a value of type T.
|
219
|
+
* The Ok type is part of the Result pattern and provides type-safe
|
220
|
+
* access to success values.
|
221
|
+
*
|
222
|
+
* @template T - The type of the success value
|
223
|
+
*/
|
224
|
+
type Ok<T> = BaseResult<T, never> & OkBaseResult<T> & {
|
225
|
+
value: T;
|
226
|
+
tag: "Ok";
|
227
|
+
};
|
228
|
+
/**
|
229
|
+
* Error type with default error tag.
|
230
|
+
*
|
231
|
+
* Represents a failed computation result with an error of type E.
|
232
|
+
* The Err type is part of the Result pattern and provides type-safe
|
233
|
+
* access to error values.
|
234
|
+
*
|
235
|
+
* @template E - The type of the error value
|
236
|
+
*/
|
237
|
+
type Err<E> = BaseResult<never, E> & ErrBaseResult<E> & {
|
238
|
+
error: E;
|
239
|
+
tag: "Err";
|
240
|
+
};
|
241
|
+
/**
|
242
|
+
* Result type that can be either Ok or Err.
|
243
|
+
*
|
244
|
+
* This is the main type used for error handling in a functional way.
|
245
|
+
* It ensures type safety by requiring that the error type E is different
|
246
|
+
* from the success type T. This prevents ambiguous cases where the same
|
247
|
+
* type could represent both success and failure.
|
248
|
+
*
|
249
|
+
* @template T - The type of the success value
|
250
|
+
* @template E - The type of the error value (must be different from T)
|
251
|
+
*
|
252
|
+
* @example
|
253
|
+
* // Valid usage
|
254
|
+
* let result: Result<string, Error>
|
255
|
+
* result = ok("success")
|
256
|
+
* result = err(new Error("error"))
|
257
|
+
*
|
258
|
+
* // Invalid usage - Error type cannot be same as success type
|
259
|
+
* let invalid: Result<Error, Error> // type error
|
260
|
+
*
|
261
|
+
* // With custom tags
|
262
|
+
* result = ok("success", "ValidData")
|
263
|
+
* result = err(new Error("error"), "ValidationError")
|
264
|
+
*/
|
265
|
+
type Result<T, E> = [E] extends [T] ? never : Ok<T> | Err<E>;
|
266
|
+
/**
|
267
|
+
* Tagged result type that allows custom tags while preserving the base type.
|
268
|
+
*
|
269
|
+
* This type allows adding custom string tags to Ok and Err types while
|
270
|
+
* maintaining their original functionality. This is useful for adding
|
271
|
+
* more context to results or categorizing different types of successes
|
272
|
+
* and failures.
|
273
|
+
*
|
274
|
+
* @template T - The base result type (Ok<U> or Err<E>)
|
275
|
+
* @template Tag - The string literal type for the custom tag
|
276
|
+
*/
|
277
|
+
type Tagged<T, Tag extends string> = T extends Ok<infer U> ? WithTag<Ok<U>, Tag> : T extends Err<infer E> ? WithTag<Err<E>, Tag> : never;
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Creates an error Result type that wraps an error value.
|
281
|
+
*
|
282
|
+
* The Err type represents a failed computation and provides methods to safely
|
283
|
+
* handle the error value. It implements the Result pattern along with Ok type.
|
284
|
+
*
|
285
|
+
* @template E - The type of the error value
|
286
|
+
* @template Tag - Optional string literal type for custom tagging
|
287
|
+
*
|
288
|
+
* @param error - The error value to wrap
|
289
|
+
* @param tag - Optional custom tag for the result (defaults to "Err")
|
290
|
+
*
|
291
|
+
* @returns An Err result containing the error and associated methods:
|
292
|
+
* - isOk(): Returns false (type guard for Ok<never>)
|
293
|
+
* - isErr(): Returns true (type guard for Err<E>)
|
294
|
+
* - match(): Transforms the error using provided functions
|
295
|
+
* - pair(): Returns a tuple of [undefined, error]
|
296
|
+
* - unwrap(): Returns the raw error
|
297
|
+
*
|
298
|
+
* @example
|
299
|
+
* // Basic usage
|
300
|
+
* const result = err(new Error("failed"))
|
301
|
+
* if (result.isErr()) {
|
302
|
+
* console.log(result.error.message) // "failed"
|
303
|
+
* }
|
304
|
+
*
|
305
|
+
* // With custom tag
|
306
|
+
* const tagged = err(new Error("failed"), "ValidationError")
|
307
|
+
* console.log(tagged.tag) // "ValidationError"
|
308
|
+
*
|
309
|
+
* // Pattern matching
|
310
|
+
* result.match(
|
311
|
+
* () => {}, // never called for Err
|
312
|
+
* error => console.error(error)
|
313
|
+
* )
|
314
|
+
*/
|
315
|
+
declare function err<E>(error: E): Err<E>;
|
316
|
+
declare function err<E, const Tag extends string>(error: E, tag: Tag): Tagged<Err<E>, Tag>;
|
317
|
+
|
318
|
+
/**
|
319
|
+
* Creates a successful Result type that wraps a value.
|
320
|
+
*
|
321
|
+
* The Ok type represents a successful computation and provides methods to safely
|
322
|
+
* handle the contained value. It implements the Result pattern along with Err type.
|
323
|
+
*
|
324
|
+
* @template T - The type of the success value
|
325
|
+
* @template Tag - Optional string literal type for custom tagging
|
326
|
+
*
|
327
|
+
* @param value - The success value to wrap
|
328
|
+
* @param tag - Optional custom tag for the result (defaults to "Ok")
|
329
|
+
*
|
330
|
+
* @returns An Ok result containing the value and associated methods:
|
331
|
+
* - isOk(): Returns true (type guard for Ok<T>)
|
332
|
+
* - isErr(): Returns false (type guard for Err<never>)
|
333
|
+
* - match(): Transforms the value using provided functions
|
334
|
+
* - pair(): Returns a tuple of [value, undefined]
|
335
|
+
* - unwrap(): Returns the raw value
|
336
|
+
*
|
337
|
+
* @example
|
338
|
+
* // Basic usage
|
339
|
+
* const result = ok("success")
|
340
|
+
* if (result.isOk()) {
|
341
|
+
* console.log(result.value) // "success"
|
342
|
+
* }
|
343
|
+
*
|
344
|
+
* // With custom tag
|
345
|
+
* const tagged = ok("success", "ValidData")
|
346
|
+
* console.log(tagged.tag) // "ValidData"
|
347
|
+
*
|
348
|
+
* // Pattern matching
|
349
|
+
* result.match(
|
350
|
+
* value => console.log(value),
|
351
|
+
* () => {} // never called for Ok
|
352
|
+
* )
|
353
|
+
*
|
354
|
+
* // Pair method
|
355
|
+
* const [value, error] = result.pair()
|
356
|
+
* if (error) {
|
357
|
+
* console.log(error) // never called for Ok
|
358
|
+
* }
|
359
|
+
*
|
360
|
+
* // Unwrap method
|
361
|
+
* const unwrapped = result.unwrap()
|
362
|
+
* console.log(unwrapped) // "success"
|
363
|
+
*/
|
364
|
+
declare function ok<T>(value: T): Ok<T>;
|
365
|
+
declare function ok<T, const Tag extends string>(value: T, tag: Tag): Tagged<Ok<T>, Tag>;
|
366
|
+
|
367
|
+
declare function result<T, E extends Error>(value: T, config?: Omit<ResultConfig<T, E, string, string>, 'tagError' | 'tagOk'>): Ok<T> | Err<E>;
|
368
|
+
declare function result<T, E extends Error, TagError extends string>(value: T, config: Omit<ResultConfig<T, E, TagError, string>, 'tagOk'> & {
|
369
|
+
tagError: TagError;
|
370
|
+
}): Ok<T> | Tagged<Err<E>, TagError>;
|
371
|
+
declare function result<T, E extends Error, TagOk extends string>(value: T, config: Omit<ResultConfig<T, E, string, TagOk>, 'tagError'> & {
|
372
|
+
tagOk: TagOk;
|
373
|
+
}): Tagged<Ok<T>, TagOk> | Err<E>;
|
374
|
+
declare function result<T, E extends Error, TagError extends string, TagOk extends string>(value: T, config: ResultConfig<T, E, TagError, TagOk> & {
|
375
|
+
tagError: TagError;
|
376
|
+
tagOk: TagOk;
|
377
|
+
}): Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError>;
|
378
|
+
|
379
|
+
/**
|
380
|
+
* A functional try-catch-finally wrapper that returns a Result type.
|
381
|
+
*
|
382
|
+
* This function provides a type-safe way to handle errors by wrapping a try-catch-finally block
|
383
|
+
* in a Result type. It supports both synchronous and asynchronous error handling, custom error
|
384
|
+
* transformations, and optional tagging of success and error results.
|
385
|
+
*
|
386
|
+
* @template T - The type of the success value
|
387
|
+
* @template EC - The type of error that might be caught (must extend Error)
|
388
|
+
* @template ER - The type of error after transformation (must extend Error or Promise<Error>)
|
389
|
+
* @template TagError - Optional string literal type for error tagging
|
390
|
+
* @template TagOk - Optional string literal type for success tagging
|
391
|
+
*
|
392
|
+
* @example
|
393
|
+
* // Basic usage
|
394
|
+
* const result = tcf({
|
395
|
+
* try: () => JSON.parse('{"valid": "json"}'),
|
396
|
+
* catch: (error: SyntaxError) => new Error(`Parse failed: ${error.message}`),
|
397
|
+
* })
|
398
|
+
*
|
399
|
+
* // With custom tags and finally block
|
400
|
+
* const result = tcf({
|
401
|
+
* try: () => fetchData(),
|
402
|
+
* catch: (error: NetworkError) => new ValidationError(error.message),
|
403
|
+
* finally: () => cleanup(),
|
404
|
+
* tagOk: "FETCH_SUCCESS",
|
405
|
+
* tagError: "FETCH_ERROR"
|
406
|
+
* })
|
407
|
+
*
|
408
|
+
* // Pattern matching the result
|
409
|
+
* result.match(
|
410
|
+
* value => console.log("Success:", value),
|
411
|
+
* error => console.error("Failed:", error)
|
412
|
+
* )
|
413
|
+
*/
|
414
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string, TagOk extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagError, tagOk, }: {
|
415
|
+
try: () => T;
|
416
|
+
catch: (error: EC) => ER;
|
417
|
+
finally?: () => unknown;
|
418
|
+
tagError: TagError;
|
419
|
+
tagOk: TagOk;
|
420
|
+
}): Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError>;
|
421
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>>({ try: tryFn, catch: catchFn, finally: finallyFn, }: {
|
422
|
+
try: () => T;
|
423
|
+
catch: (error: EC) => ER;
|
424
|
+
finally?: () => unknown;
|
425
|
+
}): Ok<T> | Err<ER>;
|
426
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagOk extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagOk, }: {
|
427
|
+
try: () => T;
|
428
|
+
catch: (error: EC) => ER;
|
429
|
+
finally?: () => unknown;
|
430
|
+
tagOk: TagOk;
|
431
|
+
}): Tagged<Ok<T>, TagOk> | Err<ER>;
|
432
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagError, }: {
|
433
|
+
try: () => T;
|
434
|
+
catch: (error: EC) => ER;
|
435
|
+
finally?: () => unknown;
|
436
|
+
tagError: TagError;
|
437
|
+
}): Ok<T> | Tagged<Err<ER>, TagError>;
|
438
|
+
|
439
|
+
export { err, ok, result, tcf };
|
440
|
+
export type { Err, Ok, Result, Tagged };
|
@@ -0,0 +1,2 @@
|
|
1
|
+
function r(r,t){return{tag:t??"error",error:r,isOk:()=>!1,isErr:()=>!0,match:(t,e)=>r instanceof Promise?r.then(r=>e(r)):e(r),pair:()=>r instanceof Promise?r.then(r=>[void 0,r]):[void 0,r],unwrap:()=>r}}function t(r,t){return{tag:t??"ok",value:r,isOk:()=>!0,isErr:()=>!1,match:t=>r instanceof Promise?r.then(r=>t(r)):t(r),pair:()=>r instanceof Promise?r.then(r=>[r,void 0]):[r,void 0],unwrap:()=>r}}Object.defineProperty(exports,"__esModule",{value:!0});const e=r=>r instanceof Error;exports.err=r,exports.ok=t,exports.result=function(n,o){return(o?.isError??e)(n)?o?.tagError?r(n,o.tagError):r(n):o?.tagOk?t(n,o.tagOk):t(n)},exports.tcf=function({try:e,catch:n,finally:o,tagError:i,tagOk:a}){try{if(void 0===a)return t(e());return t(e(),a)}catch(t){if(void 0===i)return r(n(t));return r(n(t),i)}finally{o?.()}};
|
2
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/return/err.ts","../../src/lib/constants.ts","../../src/return/ok.ts","../../src/return/result.ts","../../src/return/tcf.ts"],"sourcesContent":["import { DEFAULT_TAG_ERROR } from '@/lib/constants'\nimport { ErrBaseResult } from '@/types.private'\nimport type { Err, Ok, Tagged } from '@/types.public'\n\n/**\n * Creates an error Result type that wraps an error value.\n * \n * The Err type represents a failed computation and provides methods to safely\n * handle the error value. It implements the Result pattern along with Ok type.\n * \n * @template E - The type of the error value\n * @template Tag - Optional string literal type for custom tagging\n * \n * @param error - The error value to wrap\n * @param tag - Optional custom tag for the result (defaults to \"Err\")\n * \n * @returns An Err result containing the error and associated methods:\n * - isOk(): Returns false (type guard for Ok<never>)\n * - isErr(): Returns true (type guard for Err<E>)\n * - match(): Transforms the error using provided functions\n * - pair(): Returns a tuple of [undefined, error]\n * - unwrap(): Returns the raw error\n * \n * @example\n * // Basic usage\n * const result = err(new Error(\"failed\"))\n * if (result.isErr()) {\n * console.log(result.error.message) // \"failed\"\n * }\n * \n * // With custom tag\n * const tagged = err(new Error(\"failed\"), \"ValidationError\")\n * console.log(tagged.tag) // \"ValidationError\"\n * \n * // Pattern matching\n * result.match(\n * () => {}, // never called for Err\n * error => console.error(error)\n * )\n */\nexport function err<E>(error: E): Err<E>\nexport function err<E, const Tag extends string>(error: E, tag: Tag): Tagged<Err<E>, Tag>\nexport function err<E, const Tag extends string>(error: E, tag?: Tag): Err<E> | Tagged<Err<E>, Tag> {\n const methods: ErrBaseResult<E> = {\n isOk: (): this is Ok<never> => false,\n isErr: (): this is Err<E> => true,\n match: <ROk, RErr>(_ok: (value: never) => ROk, err: (error: Awaited<E>) => RErr) => {\n if (error instanceof Promise) {\n return error.then(e => err(e as Awaited<E>)) as E extends Promise<any> ? Promise<RErr> : RErr\n }\n return err(error as Awaited<E>) as E extends Promise<any> ? never : RErr\n },\n pair: () => {\n if (error instanceof Promise) {\n return error.then(e => [undefined, e]) as E extends Promise<any> ? Promise<[undefined, Awaited<E>]> : [undefined, Awaited<E>]\n }\n return [undefined, error] as E extends Promise<any> ? never : [undefined, E]\n },\n unwrap: () => error,\n }\n\n const props: Omit<Err<E> | Tagged<Err<E>, Tag>, keyof typeof methods> = {\n tag: (tag ?? DEFAULT_TAG_ERROR) as Tag extends string ? Tag : 'Err',\n error\n }\n\n // @ts-expect-error - BaseResult<never, E> is not assignable to ErrBaseResult<E> - this is used for common methods\n // for Ok | Err types so they dont require \"is\" checks. However any type errors should be caught by methods and props declarations\n return {\n ...props,\n ...methods,\n }\n}\n\n","export const DEFAULT_TAG_ERROR = 'error'\nexport const DEFAULT_TAG_OK = 'ok'","import { DEFAULT_TAG_OK } from '@/lib/constants'\nimport { OkBaseResult } from '@/types.private'\nimport type { Err, Ok, Tagged } from '@/types.public'\n\n/**\n * Creates a successful Result type that wraps a value.\n * \n * The Ok type represents a successful computation and provides methods to safely\n * handle the contained value. It implements the Result pattern along with Err type.\n * \n * @template T - The type of the success value\n * @template Tag - Optional string literal type for custom tagging\n * \n * @param value - The success value to wrap\n * @param tag - Optional custom tag for the result (defaults to \"Ok\")\n * \n * @returns An Ok result containing the value and associated methods:\n * - isOk(): Returns true (type guard for Ok<T>)\n * - isErr(): Returns false (type guard for Err<never>)\n * - match(): Transforms the value using provided functions\n * - pair(): Returns a tuple of [value, undefined]\n * - unwrap(): Returns the raw value\n * \n * @example\n * // Basic usage\n * const result = ok(\"success\")\n * if (result.isOk()) {\n * console.log(result.value) // \"success\"\n * }\n * \n * // With custom tag\n * const tagged = ok(\"success\", \"ValidData\")\n * console.log(tagged.tag) // \"ValidData\"\n * \n * // Pattern matching\n * result.match(\n * value => console.log(value),\n * () => {} // never called for Ok\n * )\n * \n * // Pair method\n * const [value, error] = result.pair()\n * if (error) {\n * console.log(error) // never called for Ok\n * }\n * \n * // Unwrap method\n * const unwrapped = result.unwrap()\n * console.log(unwrapped) // \"success\"\n */\nexport function ok<T>(value: T): Ok<T>\nexport function ok<T, const Tag extends string>(value: T, tag: Tag): Tagged<Ok<T>, Tag>\nexport function ok<T, const Tag extends string>(value: T, tag?: Tag): Ok<T> | Tagged<Ok<T>, Tag> {\n const methods: OkBaseResult<T> = {\n isOk: (): this is Ok<T> => true,\n isErr: (): this is Err<never> => false,\n match: <ROk>(ok: (value: Awaited<T>) => ROk) => {\n if (value instanceof Promise) {\n return value.then(v => ok(v as Awaited<T>)) as T extends Promise<any> ? Promise<ROk> : ROk\n }\n return ok(value as Awaited<T>) as T extends Promise<any> ? never : ROk\n },\n pair: () => {\n if (value instanceof Promise) {\n return value.then(v => [v as Awaited<T>, undefined]) as T extends Promise<any> ? Promise<[Awaited<T>, undefined]> : [T, undefined]\n }\n return [value as Awaited<T>, undefined] as T extends Promise<any> ? never : [T, undefined]\n },\n unwrap: () => value,\n }\n\n const props: Omit<Ok<T> | Tagged<Ok<T>, Tag>, keyof typeof methods> = {\n tag: (tag ?? DEFAULT_TAG_OK) as Tag extends string ? Tag : 'Ok',\n value\n }\n\n // @ts-expect-error - BaseResult<T, never> is not assignable to OkBaseResult<T> - this is used for common methods\n // for Ok | Err types so they dont require \"is\" checks. However any type errors should be caught by methods and props declarations\n return {\n ...props,\n ...methods,\n }\n}\n","import { DEFAULT_TAG_ERROR, DEFAULT_TAG_OK } from \"@/lib/constants\";\nimport { ResultConfig } from \"@/types.private\";\nimport { err } from \"./err\";\nimport { Err, Ok, Tagged } from \"@/types.public\";\nimport { ok } from \"./ok\";\n\nconst defaultIsError = <T, E extends Error>(value: T | E): value is E => value instanceof Error \n\n// No tags provided\nexport function result<T, E extends Error>(\n value: T,\n config?: Omit<ResultConfig<T, E, string, string>, 'tagError' | 'tagOk'>\n): Ok<T> | Err<E>;\n\n// Only tagError provided\nexport function result<T, E extends Error, TagError extends string>(\n value: T,\n config: Omit<ResultConfig<T, E, TagError, string>, 'tagOk'> & { tagError: TagError }\n): Ok<T> | Tagged<Err<E>, TagError>;\n\n// Only tagOk provided\nexport function result<T, E extends Error, TagOk extends string>(\n value: T,\n config: Omit<ResultConfig<T, E, string, TagOk>, 'tagError'> & { tagOk: TagOk }\n): Tagged<Ok<T>, TagOk> | Err<E>;\n\n// Both tags provided\nexport function result<T, E extends Error, TagError extends string, TagOk extends string>(\n value: T,\n config: ResultConfig<T, E, TagError, TagOk> & { tagError: TagError; tagOk: TagOk }\n): Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError>;\n\n// Implementation\nexport function result<T, E extends Error, TagError extends string = typeof DEFAULT_TAG_ERROR, TagOk extends string = typeof DEFAULT_TAG_OK>(\n value: T,\n config?: ResultConfig<T, E, TagError, TagOk>\n): Ok<T> | Err<E> | Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError> {\n const isError = config?.isError ?? defaultIsError<T, E>\n\n const processValue = (val: T | E) => {\n if (isError(val)) {\n return config?.tagError \n ? err(val, config.tagError) as Tagged<Err<E>, TagError>\n : err(val) as Err<E>\n }\n return config?.tagOk\n ? ok(val, config.tagOk) as Tagged<Ok<T>, TagOk>\n : ok(val) as Ok<T>\n }\n\n return processValue(value)\n}\n","import { err } from './err'\nimport { ok } from './ok'\nimport type { Ok, Err, Tagged } from '@/types.public'\n\n/**\n * A functional try-catch-finally wrapper that returns a Result type.\n * \n * This function provides a type-safe way to handle errors by wrapping a try-catch-finally block\n * in a Result type. It supports both synchronous and asynchronous error handling, custom error\n * transformations, and optional tagging of success and error results.\n * \n * @template T - The type of the success value\n * @template EC - The type of error that might be caught (must extend Error)\n * @template ER - The type of error after transformation (must extend Error or Promise<Error>)\n * @template TagError - Optional string literal type for error tagging\n * @template TagOk - Optional string literal type for success tagging\n * \n * @example\n * // Basic usage\n * const result = tcf({\n * try: () => JSON.parse('{\"valid\": \"json\"}'),\n * catch: (error: SyntaxError) => new Error(`Parse failed: ${error.message}`),\n * })\n * \n * // With custom tags and finally block\n * const result = tcf({\n * try: () => fetchData(),\n * catch: (error: NetworkError) => new ValidationError(error.message),\n * finally: () => cleanup(),\n * tagOk: \"FETCH_SUCCESS\",\n * tagError: \"FETCH_ERROR\"\n * })\n * \n * // Pattern matching the result\n * result.match(\n * value => console.log(\"Success:\", value),\n * error => console.error(\"Failed:\", error)\n * )\n */\n\n// Overload 4: Both tags provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string, TagOk extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagError,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError: TagError\n tagOk: TagOk\n}): Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError>\n\n// Overload 1: No tags provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n}): Ok<T> | Err<ER>\n\n// Overload 2: Only tagOk provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagOk extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagOk: TagOk\n}): Tagged<Ok<T>, TagOk> | Err<ER>\n\n// Overload 3: Only tagError provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagError,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError: TagError\n}): Ok<T> | Tagged<Err<ER>, TagError>\n\n\n// Implementation\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string = \"error\", TagOk extends string = \"ok\">({\n try: tryFn,\n catch: catchFn,\n finally: finallyFn,\n tagError,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError?: TagError\n tagOk?: TagOk\n}): Ok<T> | Err<ER> | Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError> {\n try {\n if (tagOk === undefined) {\n return ok(tryFn()) as Ok<T>\n }\n return ok(tryFn(), tagOk) as Tagged<Ok<T>, TagOk>\n } catch (error) {\n if (tagError === undefined) {\n return err(catchFn(error as EC)) as Err<ER>\n }\n return err(catchFn(error as EC), tagError) as Tagged<Err<ER>, TagError>\n } finally {\n finallyFn?.()\n }\n}\n\n/**\n * Creates a Result from a value that might be an error.\n * \n * This function provides a convenient way to create a Result type from a value\n * that might be either a success value or an error. It uses a type guard to\n * determine if the value is an error, and supports custom tagging.\n * \n * @template T - The type of the success value\n * @template E - The type of the error value (must extend Error)\n * @template TagError - Optional string literal type for error tagging\n * @template TagOk - Optional string literal type for success tagging\n * \n * @param value - The value to wrap in a Result\n * @param config - Optional configuration object\n * @param config.isError - Custom type guard for error detection\n * @param config.tagError - Custom tag for error results\n * @param config.tagOk - Custom tag for success results\n * \n * @example\n * // Basic usage\n * const data = await fetchData()\n * const result = result(data)\n * \n * // With custom error detection\n * const result = result(value, {\n * isError: (v): v is CustomError => v instanceof CustomError,\n * tagOk: \"VALID_DATA\",\n * tagError: \"INVALID_DATA\"\n * })\n */"],"names":["err","error","tag","isOk","isErr","match","_ok","Promise","then","e","pair","undefined","unwrap","ok","value","v","defaultIsError","Error","config","isError","tagError","tagOk","try","tryFn","catch","catchFn","finally","finallyFn"],"mappings":"AA0CO,SAASA,EAAiCC,CAAQ,CAAEC,CAAS,EA0BlE,MAAO,CANLA,IAAMA,GC9DuB,QD+D7BD,MAAAA,EAnBAE,KAAM,IAAyB,CAAA,EAC/BC,MAAO,IAAsB,CAAA,EAC7BC,MAAO,CAAYC,EAA4BN,IAC7C,AAAIC,aAAiBM,QACZN,EAAMO,IAAI,CAACC,AAAAA,GAAKT,EAAIS,IAEtBT,EAAIC,GAEbS,KAAM,IACJ,AAAIT,aAAiBM,QACZN,EAAMO,IAAI,CAACC,AAAAA,GAAK,CAACE,KAAAA,EAAWF,EAAE,EAEhC,CAACE,KAAAA,EAAWV,EAAM,CAE3BW,OAAQ,IAAMX,CAahB,CACF,CEpBO,SAASY,EAAgCC,CAAQ,CAAEZ,CAAS,EA0BjE,MAAO,CANLA,IAAMA,GDvEoB,KCwE1BY,MAAAA,EAnBAX,KAAM,IAAqB,CAAA,EAC3BC,MAAO,IAA0B,CAAA,EACjCC,MAAO,AAAMQ,GACX,AAAIC,aAAiBP,QACZO,EAAMN,IAAI,CAACO,AAAAA,GAAKF,EAAGE,IAErBF,EAAGC,GAEZJ,KAAM,IACJ,AAAII,aAAiBP,QACZO,EAAMN,IAAI,CAACO,AAAAA,GAAK,CAACA,EAAiBJ,KAAAA,EAAU,EAE9C,CAACG,EAAqBH,KAAAA,EAAU,CAEzCC,OAAQ,IAAME,CAahB,CACF,wDC5EA,MAAME,EAAiB,AAAqBF,GAA6BA,aAAiBG,gDA2BnF,SACLH,CAAQ,CACRI,CAA4C,EAe5C,MAVE,AAAIC,AAHUD,CAAAA,GAAQC,SAAWH,CAAAA,EAafF,GATTI,GAAQE,SACXpB,EAQYc,EARHI,EAAOE,QAAQ,EACxBpB,EAOYc,GALXI,GAAQG,MACXR,EAIcC,EAJNI,EAAOG,KAAK,EACpBR,EAGcC,EACtB,cCuDO,SAAqI,CAC1IQ,IAAKC,CAAK,CACVC,MAAOC,CAAO,CACdC,QAASC,CAAS,CAClBP,SAAAA,CAAQ,CACRC,MAAAA,CAAK,CAON,EACC,GAAI,CACF,GAAIA,AAAUV,KAAAA,IAAVU,EACF,OAAOR,EAAGU,KAEZ,OAAOV,EAAGU,IAASF,EACrB,CAAE,MAAOpB,EAAO,CACd,GAAImB,AAAaT,KAAAA,IAAbS,EACF,OAAOpB,EAAIyB,EAAQxB,IAErB,OAAOD,EAAIyB,EAAQxB,GAAcmB,UACzB,CACRO,KACF,CACF"}
|
@@ -0,0 +1,440 @@
|
|
1
|
+
/**
|
2
|
+
* Base result type with common functionality.
|
3
|
+
*
|
4
|
+
* This type provides the core methods shared between Ok and Err types.
|
5
|
+
* It includes type guards and value access methods that are essential
|
6
|
+
* for the Result pattern implementation.
|
7
|
+
*
|
8
|
+
* @template T - The type of the success value
|
9
|
+
* @template E - The type of the error value
|
10
|
+
*/
|
11
|
+
type BaseResult<T, E> = {
|
12
|
+
/**
|
13
|
+
* Type guard that checks if this result is an Ok value.
|
14
|
+
* @returns true if the result is Ok<T>, false otherwise
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* const result = ok("success")
|
18
|
+
* if (result.isOk()) {
|
19
|
+
* // TypeScript knows result.value exists here
|
20
|
+
* console.log(result.value) // "success"
|
21
|
+
* }
|
22
|
+
*
|
23
|
+
* @example
|
24
|
+
* const result = err(new Error("failed"))
|
25
|
+
* if (!result.isOk()) {
|
26
|
+
* // TypeScript knows this is an Err
|
27
|
+
* console.log(result.error.message) // "failed"
|
28
|
+
* }
|
29
|
+
*/
|
30
|
+
isOk: () => this is Ok<T>;
|
31
|
+
/**
|
32
|
+
* Type guard that checks if this result is an Err value.
|
33
|
+
* @returns true if the result is Err<E>, false otherwise
|
34
|
+
*
|
35
|
+
* @example
|
36
|
+
* const result = err(new Error("failed"))
|
37
|
+
* if (result.isErr()) {
|
38
|
+
* // TypeScript knows result.error exists here
|
39
|
+
* console.log(result.error.message) // "failed"
|
40
|
+
* }
|
41
|
+
*
|
42
|
+
* @example
|
43
|
+
* const result = ok("success")
|
44
|
+
* if (!result.isErr()) {
|
45
|
+
* // TypeScript knows this is an Ok
|
46
|
+
* console.log(result.value) // "success"
|
47
|
+
* }
|
48
|
+
*/
|
49
|
+
isErr: () => this is Err<E>;
|
50
|
+
/**
|
51
|
+
* Unwraps the result to get the raw value.
|
52
|
+
* @returns The contained value (T) if Ok, or the error (E) if Err
|
53
|
+
*
|
54
|
+
* @example
|
55
|
+
* const okResult = ok("success")
|
56
|
+
* console.log(okResult.unwrap()) // "success"
|
57
|
+
*
|
58
|
+
* @example
|
59
|
+
* const errResult = err(new Error("failed"))
|
60
|
+
* console.log(errResult.unwrap()) // Error: failed
|
61
|
+
*/
|
62
|
+
unwrap: () => T | E;
|
63
|
+
};
|
64
|
+
/**
|
65
|
+
* Extended base type for Ok results with success-specific methods.
|
66
|
+
*
|
67
|
+
* This type adds methods specific to handling success values, including
|
68
|
+
* pattern matching and tuple conversion. It handles both synchronous and
|
69
|
+
* asynchronous (Promise) values.
|
70
|
+
*
|
71
|
+
* @template T - The type of the success value
|
72
|
+
*/
|
73
|
+
type OkBaseResult<T> = BaseResult<T, never> & {
|
74
|
+
/**
|
75
|
+
* Pattern matches on the result, transforming the success value.
|
76
|
+
* For Ok results, only the ok function is called.
|
77
|
+
*
|
78
|
+
* @template ROk - The type to transform the success value to
|
79
|
+
* @template RErr - The type that would be returned for errors (never used for Ok)
|
80
|
+
* @param ok - Function to transform the success value
|
81
|
+
* @param _err - Optional function for error case (never called for Ok)
|
82
|
+
* @returns Transformed success value, wrapped in Promise if T is a Promise
|
83
|
+
*
|
84
|
+
* @example
|
85
|
+
* // Synchronous value
|
86
|
+
* const result = ok(5)
|
87
|
+
* const doubled = result.match(
|
88
|
+
* value => value * 2,
|
89
|
+
* () => 0 // never called for Ok
|
90
|
+
* ) // doubled = 10
|
91
|
+
*
|
92
|
+
* @example
|
93
|
+
* // Async value
|
94
|
+
* const result = ok(Promise.resolve(5))
|
95
|
+
* const doubled = await result.match(
|
96
|
+
* async value => value * 2,
|
97
|
+
* () => 0
|
98
|
+
* ) // doubled = 10
|
99
|
+
*/
|
100
|
+
match: <ROk, RErr>(ok: (value: Awaited<T>) => ROk, _err?: (error: never) => RErr) => T extends Promise<any> ? Promise<ROk> : ROk;
|
101
|
+
/**
|
102
|
+
* Converts the result to a tuple of [value, undefined].
|
103
|
+
* This is useful for destructuring and handling both success and error cases uniformly.
|
104
|
+
*
|
105
|
+
* @returns A tuple where the first element is the success value and the second is undefined,
|
106
|
+
* wrapped in Promise if T is a Promise
|
107
|
+
*
|
108
|
+
* @example
|
109
|
+
* // Synchronous value
|
110
|
+
* const result = ok("success")
|
111
|
+
* const [value, error] = result.pair()
|
112
|
+
* console.log(value) // "success"
|
113
|
+
* console.log(error) // undefined
|
114
|
+
*
|
115
|
+
* @example
|
116
|
+
* // Async value
|
117
|
+
* const result = ok(Promise.resolve("success"))
|
118
|
+
* const [value, error] = await result.pair()
|
119
|
+
* console.log(value) // "success"
|
120
|
+
* console.log(error) // undefined
|
121
|
+
*/
|
122
|
+
pair: () => T extends Promise<any> ? Promise<[Awaited<T>, undefined]> : [T, undefined];
|
123
|
+
};
|
124
|
+
/**
|
125
|
+
* Extended base type for Err results with error-specific methods.
|
126
|
+
*
|
127
|
+
* This type adds methods specific to handling error values, including
|
128
|
+
* pattern matching and tuple conversion. It handles both synchronous and
|
129
|
+
* asynchronous (Promise) errors.
|
130
|
+
*
|
131
|
+
* @template E - The type of the error value
|
132
|
+
*/
|
133
|
+
type ErrBaseResult<E> = BaseResult<never, E> & {
|
134
|
+
/**
|
135
|
+
* Pattern matches on the result, transforming the error value.
|
136
|
+
* For Err results, only the err function is called.
|
137
|
+
*
|
138
|
+
* @template ROk - The type that would be returned for success (never used for Err)
|
139
|
+
* @template RErr - The type to transform the error value to
|
140
|
+
* @param _ok - Function for success case (never called for Err)
|
141
|
+
* @param err - Function to transform the error value
|
142
|
+
* @returns Transformed error value, wrapped in Promise if E is a Promise
|
143
|
+
*
|
144
|
+
* @example
|
145
|
+
* // Synchronous error
|
146
|
+
* const result = err(new Error("failed"))
|
147
|
+
* const message = result.match(
|
148
|
+
* () => "", // never called for Err
|
149
|
+
* error => `Error: ${error.message}`
|
150
|
+
* ) // message = "Error: failed"
|
151
|
+
*
|
152
|
+
* @example
|
153
|
+
* // Async error
|
154
|
+
* const result = err(Promise.resolve(new Error("failed")))
|
155
|
+
* const message = await result.match(
|
156
|
+
* () => "",
|
157
|
+
* async error => `Error: ${error.message}`
|
158
|
+
* ) // message = "Error: failed"
|
159
|
+
*/
|
160
|
+
match: <ROk, RErr>(_ok: (value: never) => ROk, err: (error: Awaited<E>) => RErr) => E extends Promise<any> ? Promise<RErr> : RErr;
|
161
|
+
/**
|
162
|
+
* Converts the result to a tuple of [undefined, error].
|
163
|
+
* This is useful for destructuring and handling both success and error cases uniformly.
|
164
|
+
*
|
165
|
+
* @returns A tuple where the first element is undefined and the second is the error value,
|
166
|
+
* wrapped in Promise if E is a Promise
|
167
|
+
*
|
168
|
+
* @example
|
169
|
+
* // Synchronous error
|
170
|
+
* const result = err(new Error("failed"))
|
171
|
+
* const [value, error] = result.pair()
|
172
|
+
* console.log(value) // undefined
|
173
|
+
* console.log(error.message) // "failed"
|
174
|
+
*
|
175
|
+
* @example
|
176
|
+
* // Async error
|
177
|
+
* const result = err(Promise.resolve(new Error("failed")))
|
178
|
+
* const [value, error] = await result.pair()
|
179
|
+
* console.log(value) // undefined
|
180
|
+
* console.log(error.message) // "failed"
|
181
|
+
*/
|
182
|
+
pair: () => E extends Promise<any> ? Promise<[undefined, Awaited<E>]> : [undefined, E];
|
183
|
+
};
|
184
|
+
/**
|
185
|
+
* Helper type to create a tagged variant of a result type.
|
186
|
+
*
|
187
|
+
* This type modifies the tag property of a result type while preserving
|
188
|
+
* all other properties and methods. It's used internally to implement
|
189
|
+
* custom tagging for both Ok and Err types.
|
190
|
+
*
|
191
|
+
* @template T - The base result type to modify
|
192
|
+
* @template Tag - The string literal type for the new tag
|
193
|
+
*
|
194
|
+
* @example
|
195
|
+
* // Tagged Ok result
|
196
|
+
* type SuccessResult = WithTag<Ok<string>, "SUCCESS">
|
197
|
+
* const result: SuccessResult = ok("data", "SUCCESS")
|
198
|
+
* console.log(result.tag) // "SUCCESS"
|
199
|
+
*
|
200
|
+
* @example
|
201
|
+
* // Tagged Err result
|
202
|
+
* type ValidationError = WithTag<Err<Error>, "VALIDATION">
|
203
|
+
* const error: ValidationError = err(new Error("invalid"), "VALIDATION")
|
204
|
+
* console.log(error.tag) // "VALIDATION"
|
205
|
+
*/
|
206
|
+
type WithTag<T, Tag extends string> = Omit<T, 'tag'> & {
|
207
|
+
tag: Tag;
|
208
|
+
};
|
209
|
+
type ResultConfig<T, E extends Error, TagError extends string, TagOk extends string> = Partial<{
|
210
|
+
isError: (value: T | E) => value is E;
|
211
|
+
tagError: TagError;
|
212
|
+
tagOk: TagOk;
|
213
|
+
}>;
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Success type that preserves tag information.
|
217
|
+
*
|
218
|
+
* Represents a successful computation result with a value of type T.
|
219
|
+
* The Ok type is part of the Result pattern and provides type-safe
|
220
|
+
* access to success values.
|
221
|
+
*
|
222
|
+
* @template T - The type of the success value
|
223
|
+
*/
|
224
|
+
type Ok<T> = BaseResult<T, never> & OkBaseResult<T> & {
|
225
|
+
value: T;
|
226
|
+
tag: "Ok";
|
227
|
+
};
|
228
|
+
/**
|
229
|
+
* Error type with default error tag.
|
230
|
+
*
|
231
|
+
* Represents a failed computation result with an error of type E.
|
232
|
+
* The Err type is part of the Result pattern and provides type-safe
|
233
|
+
* access to error values.
|
234
|
+
*
|
235
|
+
* @template E - The type of the error value
|
236
|
+
*/
|
237
|
+
type Err<E> = BaseResult<never, E> & ErrBaseResult<E> & {
|
238
|
+
error: E;
|
239
|
+
tag: "Err";
|
240
|
+
};
|
241
|
+
/**
|
242
|
+
* Result type that can be either Ok or Err.
|
243
|
+
*
|
244
|
+
* This is the main type used for error handling in a functional way.
|
245
|
+
* It ensures type safety by requiring that the error type E is different
|
246
|
+
* from the success type T. This prevents ambiguous cases where the same
|
247
|
+
* type could represent both success and failure.
|
248
|
+
*
|
249
|
+
* @template T - The type of the success value
|
250
|
+
* @template E - The type of the error value (must be different from T)
|
251
|
+
*
|
252
|
+
* @example
|
253
|
+
* // Valid usage
|
254
|
+
* let result: Result<string, Error>
|
255
|
+
* result = ok("success")
|
256
|
+
* result = err(new Error("error"))
|
257
|
+
*
|
258
|
+
* // Invalid usage - Error type cannot be same as success type
|
259
|
+
* let invalid: Result<Error, Error> // type error
|
260
|
+
*
|
261
|
+
* // With custom tags
|
262
|
+
* result = ok("success", "ValidData")
|
263
|
+
* result = err(new Error("error"), "ValidationError")
|
264
|
+
*/
|
265
|
+
type Result<T, E> = [E] extends [T] ? never : Ok<T> | Err<E>;
|
266
|
+
/**
|
267
|
+
* Tagged result type that allows custom tags while preserving the base type.
|
268
|
+
*
|
269
|
+
* This type allows adding custom string tags to Ok and Err types while
|
270
|
+
* maintaining their original functionality. This is useful for adding
|
271
|
+
* more context to results or categorizing different types of successes
|
272
|
+
* and failures.
|
273
|
+
*
|
274
|
+
* @template T - The base result type (Ok<U> or Err<E>)
|
275
|
+
* @template Tag - The string literal type for the custom tag
|
276
|
+
*/
|
277
|
+
type Tagged<T, Tag extends string> = T extends Ok<infer U> ? WithTag<Ok<U>, Tag> : T extends Err<infer E> ? WithTag<Err<E>, Tag> : never;
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Creates an error Result type that wraps an error value.
|
281
|
+
*
|
282
|
+
* The Err type represents a failed computation and provides methods to safely
|
283
|
+
* handle the error value. It implements the Result pattern along with Ok type.
|
284
|
+
*
|
285
|
+
* @template E - The type of the error value
|
286
|
+
* @template Tag - Optional string literal type for custom tagging
|
287
|
+
*
|
288
|
+
* @param error - The error value to wrap
|
289
|
+
* @param tag - Optional custom tag for the result (defaults to "Err")
|
290
|
+
*
|
291
|
+
* @returns An Err result containing the error and associated methods:
|
292
|
+
* - isOk(): Returns false (type guard for Ok<never>)
|
293
|
+
* - isErr(): Returns true (type guard for Err<E>)
|
294
|
+
* - match(): Transforms the error using provided functions
|
295
|
+
* - pair(): Returns a tuple of [undefined, error]
|
296
|
+
* - unwrap(): Returns the raw error
|
297
|
+
*
|
298
|
+
* @example
|
299
|
+
* // Basic usage
|
300
|
+
* const result = err(new Error("failed"))
|
301
|
+
* if (result.isErr()) {
|
302
|
+
* console.log(result.error.message) // "failed"
|
303
|
+
* }
|
304
|
+
*
|
305
|
+
* // With custom tag
|
306
|
+
* const tagged = err(new Error("failed"), "ValidationError")
|
307
|
+
* console.log(tagged.tag) // "ValidationError"
|
308
|
+
*
|
309
|
+
* // Pattern matching
|
310
|
+
* result.match(
|
311
|
+
* () => {}, // never called for Err
|
312
|
+
* error => console.error(error)
|
313
|
+
* )
|
314
|
+
*/
|
315
|
+
declare function err<E>(error: E): Err<E>;
|
316
|
+
declare function err<E, const Tag extends string>(error: E, tag: Tag): Tagged<Err<E>, Tag>;
|
317
|
+
|
318
|
+
/**
|
319
|
+
* Creates a successful Result type that wraps a value.
|
320
|
+
*
|
321
|
+
* The Ok type represents a successful computation and provides methods to safely
|
322
|
+
* handle the contained value. It implements the Result pattern along with Err type.
|
323
|
+
*
|
324
|
+
* @template T - The type of the success value
|
325
|
+
* @template Tag - Optional string literal type for custom tagging
|
326
|
+
*
|
327
|
+
* @param value - The success value to wrap
|
328
|
+
* @param tag - Optional custom tag for the result (defaults to "Ok")
|
329
|
+
*
|
330
|
+
* @returns An Ok result containing the value and associated methods:
|
331
|
+
* - isOk(): Returns true (type guard for Ok<T>)
|
332
|
+
* - isErr(): Returns false (type guard for Err<never>)
|
333
|
+
* - match(): Transforms the value using provided functions
|
334
|
+
* - pair(): Returns a tuple of [value, undefined]
|
335
|
+
* - unwrap(): Returns the raw value
|
336
|
+
*
|
337
|
+
* @example
|
338
|
+
* // Basic usage
|
339
|
+
* const result = ok("success")
|
340
|
+
* if (result.isOk()) {
|
341
|
+
* console.log(result.value) // "success"
|
342
|
+
* }
|
343
|
+
*
|
344
|
+
* // With custom tag
|
345
|
+
* const tagged = ok("success", "ValidData")
|
346
|
+
* console.log(tagged.tag) // "ValidData"
|
347
|
+
*
|
348
|
+
* // Pattern matching
|
349
|
+
* result.match(
|
350
|
+
* value => console.log(value),
|
351
|
+
* () => {} // never called for Ok
|
352
|
+
* )
|
353
|
+
*
|
354
|
+
* // Pair method
|
355
|
+
* const [value, error] = result.pair()
|
356
|
+
* if (error) {
|
357
|
+
* console.log(error) // never called for Ok
|
358
|
+
* }
|
359
|
+
*
|
360
|
+
* // Unwrap method
|
361
|
+
* const unwrapped = result.unwrap()
|
362
|
+
* console.log(unwrapped) // "success"
|
363
|
+
*/
|
364
|
+
declare function ok<T>(value: T): Ok<T>;
|
365
|
+
declare function ok<T, const Tag extends string>(value: T, tag: Tag): Tagged<Ok<T>, Tag>;
|
366
|
+
|
367
|
+
declare function result<T, E extends Error>(value: T, config?: Omit<ResultConfig<T, E, string, string>, 'tagError' | 'tagOk'>): Ok<T> | Err<E>;
|
368
|
+
declare function result<T, E extends Error, TagError extends string>(value: T, config: Omit<ResultConfig<T, E, TagError, string>, 'tagOk'> & {
|
369
|
+
tagError: TagError;
|
370
|
+
}): Ok<T> | Tagged<Err<E>, TagError>;
|
371
|
+
declare function result<T, E extends Error, TagOk extends string>(value: T, config: Omit<ResultConfig<T, E, string, TagOk>, 'tagError'> & {
|
372
|
+
tagOk: TagOk;
|
373
|
+
}): Tagged<Ok<T>, TagOk> | Err<E>;
|
374
|
+
declare function result<T, E extends Error, TagError extends string, TagOk extends string>(value: T, config: ResultConfig<T, E, TagError, TagOk> & {
|
375
|
+
tagError: TagError;
|
376
|
+
tagOk: TagOk;
|
377
|
+
}): Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError>;
|
378
|
+
|
379
|
+
/**
|
380
|
+
* A functional try-catch-finally wrapper that returns a Result type.
|
381
|
+
*
|
382
|
+
* This function provides a type-safe way to handle errors by wrapping a try-catch-finally block
|
383
|
+
* in a Result type. It supports both synchronous and asynchronous error handling, custom error
|
384
|
+
* transformations, and optional tagging of success and error results.
|
385
|
+
*
|
386
|
+
* @template T - The type of the success value
|
387
|
+
* @template EC - The type of error that might be caught (must extend Error)
|
388
|
+
* @template ER - The type of error after transformation (must extend Error or Promise<Error>)
|
389
|
+
* @template TagError - Optional string literal type for error tagging
|
390
|
+
* @template TagOk - Optional string literal type for success tagging
|
391
|
+
*
|
392
|
+
* @example
|
393
|
+
* // Basic usage
|
394
|
+
* const result = tcf({
|
395
|
+
* try: () => JSON.parse('{"valid": "json"}'),
|
396
|
+
* catch: (error: SyntaxError) => new Error(`Parse failed: ${error.message}`),
|
397
|
+
* })
|
398
|
+
*
|
399
|
+
* // With custom tags and finally block
|
400
|
+
* const result = tcf({
|
401
|
+
* try: () => fetchData(),
|
402
|
+
* catch: (error: NetworkError) => new ValidationError(error.message),
|
403
|
+
* finally: () => cleanup(),
|
404
|
+
* tagOk: "FETCH_SUCCESS",
|
405
|
+
* tagError: "FETCH_ERROR"
|
406
|
+
* })
|
407
|
+
*
|
408
|
+
* // Pattern matching the result
|
409
|
+
* result.match(
|
410
|
+
* value => console.log("Success:", value),
|
411
|
+
* error => console.error("Failed:", error)
|
412
|
+
* )
|
413
|
+
*/
|
414
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string, TagOk extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagError, tagOk, }: {
|
415
|
+
try: () => T;
|
416
|
+
catch: (error: EC) => ER;
|
417
|
+
finally?: () => unknown;
|
418
|
+
tagError: TagError;
|
419
|
+
tagOk: TagOk;
|
420
|
+
}): Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError>;
|
421
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>>({ try: tryFn, catch: catchFn, finally: finallyFn, }: {
|
422
|
+
try: () => T;
|
423
|
+
catch: (error: EC) => ER;
|
424
|
+
finally?: () => unknown;
|
425
|
+
}): Ok<T> | Err<ER>;
|
426
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagOk extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagOk, }: {
|
427
|
+
try: () => T;
|
428
|
+
catch: (error: EC) => ER;
|
429
|
+
finally?: () => unknown;
|
430
|
+
tagOk: TagOk;
|
431
|
+
}): Tagged<Ok<T>, TagOk> | Err<ER>;
|
432
|
+
declare function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string>({ try: tryFn, catch: catchFn, finally: finallyFn, tagError, }: {
|
433
|
+
try: () => T;
|
434
|
+
catch: (error: EC) => ER;
|
435
|
+
finally?: () => unknown;
|
436
|
+
tagError: TagError;
|
437
|
+
}): Ok<T> | Tagged<Err<ER>, TagError>;
|
438
|
+
|
439
|
+
export { err, ok, result, tcf };
|
440
|
+
export type { Err, Ok, Result, Tagged };
|
@@ -0,0 +1,2 @@
|
|
1
|
+
function r(r,t){return{tag:t??"error",error:r,isOk:()=>!1,isErr:()=>!0,match:(t,n)=>r instanceof Promise?r.then(r=>n(r)):n(r),pair:()=>r instanceof Promise?r.then(r=>[void 0,r]):[void 0,r],unwrap:()=>r}}function t(r,t){return{tag:t??"ok",value:r,isOk:()=>!0,isErr:()=>!1,match:t=>r instanceof Promise?r.then(r=>t(r)):t(r),pair:()=>r instanceof Promise?r.then(r=>[r,void 0]):[r,void 0],unwrap:()=>r}}let n=r=>r instanceof Error;function i(i,o){return(o?.isError??n)(i)?o?.tagError?r(i,o.tagError):r(i):o?.tagOk?t(i,o.tagOk):t(i)}function o({try:n,catch:i,finally:o,tagError:e,tagOk:a}){try{if(void 0===a)return t(n());return t(n(),a)}catch(t){if(void 0===e)return r(i(t));return r(i(t),e)}finally{o?.()}}export{r as err,t as ok,i as result,o as tcf};
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/return/err.ts","../../src/lib/constants.ts","../../src/return/ok.ts","../../src/return/result.ts","../../src/return/tcf.ts"],"sourcesContent":["import { DEFAULT_TAG_ERROR } from '@/lib/constants'\nimport { ErrBaseResult } from '@/types.private'\nimport type { Err, Ok, Tagged } from '@/types.public'\n\n/**\n * Creates an error Result type that wraps an error value.\n * \n * The Err type represents a failed computation and provides methods to safely\n * handle the error value. It implements the Result pattern along with Ok type.\n * \n * @template E - The type of the error value\n * @template Tag - Optional string literal type for custom tagging\n * \n * @param error - The error value to wrap\n * @param tag - Optional custom tag for the result (defaults to \"Err\")\n * \n * @returns An Err result containing the error and associated methods:\n * - isOk(): Returns false (type guard for Ok<never>)\n * - isErr(): Returns true (type guard for Err<E>)\n * - match(): Transforms the error using provided functions\n * - pair(): Returns a tuple of [undefined, error]\n * - unwrap(): Returns the raw error\n * \n * @example\n * // Basic usage\n * const result = err(new Error(\"failed\"))\n * if (result.isErr()) {\n * console.log(result.error.message) // \"failed\"\n * }\n * \n * // With custom tag\n * const tagged = err(new Error(\"failed\"), \"ValidationError\")\n * console.log(tagged.tag) // \"ValidationError\"\n * \n * // Pattern matching\n * result.match(\n * () => {}, // never called for Err\n * error => console.error(error)\n * )\n */\nexport function err<E>(error: E): Err<E>\nexport function err<E, const Tag extends string>(error: E, tag: Tag): Tagged<Err<E>, Tag>\nexport function err<E, const Tag extends string>(error: E, tag?: Tag): Err<E> | Tagged<Err<E>, Tag> {\n const methods: ErrBaseResult<E> = {\n isOk: (): this is Ok<never> => false,\n isErr: (): this is Err<E> => true,\n match: <ROk, RErr>(_ok: (value: never) => ROk, err: (error: Awaited<E>) => RErr) => {\n if (error instanceof Promise) {\n return error.then(e => err(e as Awaited<E>)) as E extends Promise<any> ? Promise<RErr> : RErr\n }\n return err(error as Awaited<E>) as E extends Promise<any> ? never : RErr\n },\n pair: () => {\n if (error instanceof Promise) {\n return error.then(e => [undefined, e]) as E extends Promise<any> ? Promise<[undefined, Awaited<E>]> : [undefined, Awaited<E>]\n }\n return [undefined, error] as E extends Promise<any> ? never : [undefined, E]\n },\n unwrap: () => error,\n }\n\n const props: Omit<Err<E> | Tagged<Err<E>, Tag>, keyof typeof methods> = {\n tag: (tag ?? DEFAULT_TAG_ERROR) as Tag extends string ? Tag : 'Err',\n error\n }\n\n // @ts-expect-error - BaseResult<never, E> is not assignable to ErrBaseResult<E> - this is used for common methods\n // for Ok | Err types so they dont require \"is\" checks. However any type errors should be caught by methods and props declarations\n return {\n ...props,\n ...methods,\n }\n}\n\n","export const DEFAULT_TAG_ERROR = 'error'\nexport const DEFAULT_TAG_OK = 'ok'","import { DEFAULT_TAG_OK } from '@/lib/constants'\nimport { OkBaseResult } from '@/types.private'\nimport type { Err, Ok, Tagged } from '@/types.public'\n\n/**\n * Creates a successful Result type that wraps a value.\n * \n * The Ok type represents a successful computation and provides methods to safely\n * handle the contained value. It implements the Result pattern along with Err type.\n * \n * @template T - The type of the success value\n * @template Tag - Optional string literal type for custom tagging\n * \n * @param value - The success value to wrap\n * @param tag - Optional custom tag for the result (defaults to \"Ok\")\n * \n * @returns An Ok result containing the value and associated methods:\n * - isOk(): Returns true (type guard for Ok<T>)\n * - isErr(): Returns false (type guard for Err<never>)\n * - match(): Transforms the value using provided functions\n * - pair(): Returns a tuple of [value, undefined]\n * - unwrap(): Returns the raw value\n * \n * @example\n * // Basic usage\n * const result = ok(\"success\")\n * if (result.isOk()) {\n * console.log(result.value) // \"success\"\n * }\n * \n * // With custom tag\n * const tagged = ok(\"success\", \"ValidData\")\n * console.log(tagged.tag) // \"ValidData\"\n * \n * // Pattern matching\n * result.match(\n * value => console.log(value),\n * () => {} // never called for Ok\n * )\n * \n * // Pair method\n * const [value, error] = result.pair()\n * if (error) {\n * console.log(error) // never called for Ok\n * }\n * \n * // Unwrap method\n * const unwrapped = result.unwrap()\n * console.log(unwrapped) // \"success\"\n */\nexport function ok<T>(value: T): Ok<T>\nexport function ok<T, const Tag extends string>(value: T, tag: Tag): Tagged<Ok<T>, Tag>\nexport function ok<T, const Tag extends string>(value: T, tag?: Tag): Ok<T> | Tagged<Ok<T>, Tag> {\n const methods: OkBaseResult<T> = {\n isOk: (): this is Ok<T> => true,\n isErr: (): this is Err<never> => false,\n match: <ROk>(ok: (value: Awaited<T>) => ROk) => {\n if (value instanceof Promise) {\n return value.then(v => ok(v as Awaited<T>)) as T extends Promise<any> ? Promise<ROk> : ROk\n }\n return ok(value as Awaited<T>) as T extends Promise<any> ? never : ROk\n },\n pair: () => {\n if (value instanceof Promise) {\n return value.then(v => [v as Awaited<T>, undefined]) as T extends Promise<any> ? Promise<[Awaited<T>, undefined]> : [T, undefined]\n }\n return [value as Awaited<T>, undefined] as T extends Promise<any> ? never : [T, undefined]\n },\n unwrap: () => value,\n }\n\n const props: Omit<Ok<T> | Tagged<Ok<T>, Tag>, keyof typeof methods> = {\n tag: (tag ?? DEFAULT_TAG_OK) as Tag extends string ? Tag : 'Ok',\n value\n }\n\n // @ts-expect-error - BaseResult<T, never> is not assignable to OkBaseResult<T> - this is used for common methods\n // for Ok | Err types so they dont require \"is\" checks. However any type errors should be caught by methods and props declarations\n return {\n ...props,\n ...methods,\n }\n}\n","import { DEFAULT_TAG_ERROR, DEFAULT_TAG_OK } from \"@/lib/constants\";\nimport { ResultConfig } from \"@/types.private\";\nimport { err } from \"./err\";\nimport { Err, Ok, Tagged } from \"@/types.public\";\nimport { ok } from \"./ok\";\n\nconst defaultIsError = <T, E extends Error>(value: T | E): value is E => value instanceof Error \n\n// No tags provided\nexport function result<T, E extends Error>(\n value: T,\n config?: Omit<ResultConfig<T, E, string, string>, 'tagError' | 'tagOk'>\n): Ok<T> | Err<E>;\n\n// Only tagError provided\nexport function result<T, E extends Error, TagError extends string>(\n value: T,\n config: Omit<ResultConfig<T, E, TagError, string>, 'tagOk'> & { tagError: TagError }\n): Ok<T> | Tagged<Err<E>, TagError>;\n\n// Only tagOk provided\nexport function result<T, E extends Error, TagOk extends string>(\n value: T,\n config: Omit<ResultConfig<T, E, string, TagOk>, 'tagError'> & { tagOk: TagOk }\n): Tagged<Ok<T>, TagOk> | Err<E>;\n\n// Both tags provided\nexport function result<T, E extends Error, TagError extends string, TagOk extends string>(\n value: T,\n config: ResultConfig<T, E, TagError, TagOk> & { tagError: TagError; tagOk: TagOk }\n): Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError>;\n\n// Implementation\nexport function result<T, E extends Error, TagError extends string = typeof DEFAULT_TAG_ERROR, TagOk extends string = typeof DEFAULT_TAG_OK>(\n value: T,\n config?: ResultConfig<T, E, TagError, TagOk>\n): Ok<T> | Err<E> | Tagged<Ok<T>, TagOk> | Tagged<Err<E>, TagError> {\n const isError = config?.isError ?? defaultIsError<T, E>\n\n const processValue = (val: T | E) => {\n if (isError(val)) {\n return config?.tagError \n ? err(val, config.tagError) as Tagged<Err<E>, TagError>\n : err(val) as Err<E>\n }\n return config?.tagOk\n ? ok(val, config.tagOk) as Tagged<Ok<T>, TagOk>\n : ok(val) as Ok<T>\n }\n\n return processValue(value)\n}\n","import { err } from './err'\nimport { ok } from './ok'\nimport type { Ok, Err, Tagged } from '@/types.public'\n\n/**\n * A functional try-catch-finally wrapper that returns a Result type.\n * \n * This function provides a type-safe way to handle errors by wrapping a try-catch-finally block\n * in a Result type. It supports both synchronous and asynchronous error handling, custom error\n * transformations, and optional tagging of success and error results.\n * \n * @template T - The type of the success value\n * @template EC - The type of error that might be caught (must extend Error)\n * @template ER - The type of error after transformation (must extend Error or Promise<Error>)\n * @template TagError - Optional string literal type for error tagging\n * @template TagOk - Optional string literal type for success tagging\n * \n * @example\n * // Basic usage\n * const result = tcf({\n * try: () => JSON.parse('{\"valid\": \"json\"}'),\n * catch: (error: SyntaxError) => new Error(`Parse failed: ${error.message}`),\n * })\n * \n * // With custom tags and finally block\n * const result = tcf({\n * try: () => fetchData(),\n * catch: (error: NetworkError) => new ValidationError(error.message),\n * finally: () => cleanup(),\n * tagOk: \"FETCH_SUCCESS\",\n * tagError: \"FETCH_ERROR\"\n * })\n * \n * // Pattern matching the result\n * result.match(\n * value => console.log(\"Success:\", value),\n * error => console.error(\"Failed:\", error)\n * )\n */\n\n// Overload 4: Both tags provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string, TagOk extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagError,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError: TagError\n tagOk: TagOk\n}): Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError>\n\n// Overload 1: No tags provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n}): Ok<T> | Err<ER>\n\n// Overload 2: Only tagOk provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagOk extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagOk: TagOk\n}): Tagged<Ok<T>, TagOk> | Err<ER>\n\n// Overload 3: Only tagError provided\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string>({\n // @ts-expect-error - Parameter renaming is required for reserved words\n try: tryFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n catch: catchFn,\n // @ts-expect-error - Parameter renaming is required for reserved words\n finally: finallyFn,\n tagError,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError: TagError\n}): Ok<T> | Tagged<Err<ER>, TagError>\n\n\n// Implementation\nexport function tcf<T, EC extends Error, ER extends Error | Promise<Error>, TagError extends string = \"error\", TagOk extends string = \"ok\">({\n try: tryFn,\n catch: catchFn,\n finally: finallyFn,\n tagError,\n tagOk,\n}: {\n try: () => T\n catch: (error: EC) => ER\n finally?: () => unknown\n tagError?: TagError\n tagOk?: TagOk\n}): Ok<T> | Err<ER> | Tagged<Ok<T>, TagOk> | Tagged<Err<ER>, TagError> {\n try {\n if (tagOk === undefined) {\n return ok(tryFn()) as Ok<T>\n }\n return ok(tryFn(), tagOk) as Tagged<Ok<T>, TagOk>\n } catch (error) {\n if (tagError === undefined) {\n return err(catchFn(error as EC)) as Err<ER>\n }\n return err(catchFn(error as EC), tagError) as Tagged<Err<ER>, TagError>\n } finally {\n finallyFn?.()\n }\n}\n\n/**\n * Creates a Result from a value that might be an error.\n * \n * This function provides a convenient way to create a Result type from a value\n * that might be either a success value or an error. It uses a type guard to\n * determine if the value is an error, and supports custom tagging.\n * \n * @template T - The type of the success value\n * @template E - The type of the error value (must extend Error)\n * @template TagError - Optional string literal type for error tagging\n * @template TagOk - Optional string literal type for success tagging\n * \n * @param value - The value to wrap in a Result\n * @param config - Optional configuration object\n * @param config.isError - Custom type guard for error detection\n * @param config.tagError - Custom tag for error results\n * @param config.tagOk - Custom tag for success results\n * \n * @example\n * // Basic usage\n * const data = await fetchData()\n * const result = result(data)\n * \n * // With custom error detection\n * const result = result(value, {\n * isError: (v): v is CustomError => v instanceof CustomError,\n * tagOk: \"VALID_DATA\",\n * tagError: \"INVALID_DATA\"\n * })\n */"],"names":["err","error","tag","isOk","isErr","match","_ok","Promise","then","e","pair","undefined","unwrap","ok","value","v","defaultIsError","Error","result","config","isError","tagError","tagOk","tcf","try","tryFn","catch","catchFn","finally","finallyFn"],"mappings":"AA0CO,SAASA,EAAiCC,CAAQ,CAAEC,CAAS,EA0BlE,MAAO,CANLA,IAAMA,GC9DuB,QD+D7BD,MAAAA,EAnBAE,KAAM,IAAyB,CAAA,EAC/BC,MAAO,IAAsB,CAAA,EAC7BC,MAAO,CAAYC,EAA4BN,IAC7C,AAAIC,aAAiBM,QACZN,EAAMO,IAAI,CAACC,AAAAA,GAAKT,EAAIS,IAEtBT,EAAIC,GAEbS,KAAM,IACJ,AAAIT,aAAiBM,QACZN,EAAMO,IAAI,CAACC,AAAAA,GAAK,CAACE,KAAAA,EAAWF,EAAE,EAEhC,CAACE,KAAAA,EAAWV,EAAM,CAE3BW,OAAQ,IAAMX,CAahB,CACF,CEpBO,SAASY,EAAgCC,CAAQ,CAAEZ,CAAS,EA0BjE,MAAO,CANLA,IAAMA,GDvEoB,KCwE1BY,MAAAA,EAnBAX,KAAM,IAAqB,CAAA,EAC3BC,MAAO,IAA0B,CAAA,EACjCC,MAAO,AAAMQ,GACX,AAAIC,aAAiBP,QACZO,EAAMN,IAAI,CAACO,AAAAA,GAAKF,EAAGE,IAErBF,EAAGC,GAEZJ,KAAM,IACJ,AAAII,aAAiBP,QACZO,EAAMN,IAAI,CAACO,AAAAA,GAAK,CAACA,EAAiBJ,KAAAA,EAAU,EAE9C,CAACG,EAAqBH,KAAAA,EAAU,CAEzCC,OAAQ,IAAME,CAahB,CACF,CC5EA,IAAME,EAAiB,AAAqBF,GAA6BA,aAAiBG,MA2BnF,SAASC,EACdJ,CAAQ,CACRK,CAA4C,EAe5C,MAVE,AAAIC,AAHUD,CAAAA,GAAQC,SAAWJ,CAAAA,EAafF,GATTK,GAAQE,SACXrB,EAQYc,EARHK,EAAOE,QAAQ,EACxBrB,EAOYc,GALXK,GAAQG,MACXT,EAIcC,EAJNK,EAAOG,KAAK,EACpBT,EAGcC,EACtB,CCuDO,SAASS,EAA4H,CAC1IC,IAAKC,CAAK,CACVC,MAAOC,CAAO,CACdC,QAASC,CAAS,CAClBR,SAAAA,CAAQ,CACRC,MAAAA,CAAK,CAON,EACC,GAAI,CACF,GAAIA,AAAUX,KAAAA,IAAVW,EACF,OAAOT,EAAGY,KAEZ,OAAOZ,EAAGY,IAASH,EACrB,CAAE,MAAOrB,EAAO,CACd,GAAIoB,AAAaV,KAAAA,IAAbU,EACF,OAAOrB,EAAI2B,EAAQ1B,IAErB,OAAOD,EAAI2B,EAAQ1B,GAAcoB,UACzB,CACRQ,KACF,CACF"}
|