@shkumbinhsn/try-catch 0.0.3 → 0.0.6
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/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/package.json +19 -15
- package/README.md +0 -152
- package/lib/try-catch.d.ts +0 -19
- package/lib/try-catch.js +0 -29
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
declare const errorSymbol: unique symbol;
|
|
2
|
+
export type Throws<T extends Error> = {
|
|
3
|
+
[errorSymbol]?: T;
|
|
4
|
+
};
|
|
5
|
+
type ExtractErrors<T> = T extends Throws<infer E> ? E : never;
|
|
6
|
+
type StripThrows<T> = T extends infer R & Throws<Error> ? R : T;
|
|
7
|
+
type DataError<T> = [StripThrows<T>, null] | [null, Error | ExtractErrors<T>];
|
|
8
|
+
type TryCatchReturn<T> = T extends Promise<infer R> ? Promise<DataError<R>> : DataError<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Executes a function within a try-catch block and returns a tuple [data, error].
|
|
11
|
+
*
|
|
12
|
+
* @param fn - The function to execute. Can be synchronous or return a Promise.
|
|
13
|
+
* @returns A tuple where:
|
|
14
|
+
* - For success: [data, null] where data is the function's return value
|
|
15
|
+
* - For failure: [null, error] where error is the caught exception
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Synchronous usage
|
|
19
|
+
* const [data, error] = tryCatch(() => riskyFunction());
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Asynchronous usage
|
|
23
|
+
* const [data, error] = await tryCatch(() => asyncRiskyFunction());
|
|
24
|
+
*/
|
|
25
|
+
export declare function tryCatch<T>(fn: () => T): TryCatchReturn<T>;
|
|
26
|
+
interface TcBuilder<T> {
|
|
27
|
+
mightThrow<E extends Error>(): T & Throws<E>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Brands a return value with potential error types for tryCatch inference.
|
|
31
|
+
* Uses a fluent API for declaring errors.
|
|
32
|
+
*
|
|
33
|
+
* @param value - The value to return
|
|
34
|
+
* @returns A builder with mightThrow() to declare error types
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* function fetchUser() {
|
|
38
|
+
* const user = getUser();
|
|
39
|
+
* return tc(user).mightThrow<APIError | NetworkError>();
|
|
40
|
+
* }
|
|
41
|
+
*/
|
|
42
|
+
export declare function tc<T>(value: T): TcBuilder<T>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,WAAW,eAAW,CAAC;AAI7B,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,KAAK,IAAI;IACpC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;CACnB,CAAC;AAEF,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE9D,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEhE,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAC/C,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACrB,SAAS,CAAC,CAAC,CAAC,CAAC;AAEjB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAc1D;AAED,UAAU,SAAS,CAAC,CAAC;IACnB,UAAU,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAM5C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const errorSymbol = Symbol();
|
|
2
|
+
/**
|
|
3
|
+
* Executes a function within a try-catch block and returns a tuple [data, error].
|
|
4
|
+
*
|
|
5
|
+
* @param fn - The function to execute. Can be synchronous or return a Promise.
|
|
6
|
+
* @returns A tuple where:
|
|
7
|
+
* - For success: [data, null] where data is the function's return value
|
|
8
|
+
* - For failure: [null, error] where error is the caught exception
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Synchronous usage
|
|
12
|
+
* const [data, error] = tryCatch(() => riskyFunction());
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Asynchronous usage
|
|
16
|
+
* const [data, error] = await tryCatch(() => asyncRiskyFunction());
|
|
17
|
+
*/
|
|
18
|
+
export function tryCatch(fn) {
|
|
19
|
+
try {
|
|
20
|
+
const result = fn();
|
|
21
|
+
if (result instanceof Promise) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
result
|
|
24
|
+
.then((data) => resolve([data, null]))
|
|
25
|
+
.catch((error) => resolve([null, error]));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return [result, null];
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
return [null, e];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Brands a return value with potential error types for tryCatch inference.
|
|
36
|
+
* Uses a fluent API for declaring errors.
|
|
37
|
+
*
|
|
38
|
+
* @param value - The value to return
|
|
39
|
+
* @returns A builder with mightThrow() to declare error types
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* function fetchUser() {
|
|
43
|
+
* const user = getUser();
|
|
44
|
+
* return tc(user).mightThrow<APIError | NetworkError>();
|
|
45
|
+
* }
|
|
46
|
+
*/
|
|
47
|
+
export function tc(value) {
|
|
48
|
+
return {
|
|
49
|
+
mightThrow() {
|
|
50
|
+
return value;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC;AAkB7B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,QAAQ,CAAI,EAAW;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,MAAM;qBACH,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;qBACrC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC,CAAsB,CAAC;QAC1B,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,IAAI,CAAsB,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,EAAE,CAAC,CAAsB,CAAC;IACxC,CAAC;AACH,CAAC;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO;QACL,UAAU;YACR,OAAO,KAAsB,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shkumbinhsn/try-catch",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "A utility package for handling try-catch blocks in TypeScript.",
|
|
5
|
-
"main": "./
|
|
6
|
-
"module": "./
|
|
7
|
-
"types": "./
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "A utility package for handling try-catch blocks in TypeScript with full type inference.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"types": "./
|
|
11
|
-
"import": "./
|
|
12
|
-
"require": "./
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"
|
|
16
|
+
"dist"
|
|
17
17
|
],
|
|
18
18
|
"engines": {
|
|
19
19
|
"node": ">=16"
|
|
@@ -22,11 +22,10 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"url": "git+https://github.com/shkumbinhasani/ts-try-catch.git"
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
30
29
|
},
|
|
31
30
|
"keywords": [
|
|
32
31
|
"typescript",
|
|
@@ -40,7 +39,12 @@
|
|
|
40
39
|
],
|
|
41
40
|
"author": "Shkumbin Hasani",
|
|
42
41
|
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/shkumbinhasani/ts-try-catch.git",
|
|
45
|
+
"directory": "packages/try-catch"
|
|
46
|
+
},
|
|
43
47
|
"devDependencies": {
|
|
44
|
-
"
|
|
48
|
+
"vitest": "^1.2.0"
|
|
45
49
|
}
|
|
46
50
|
}
|
package/README.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
[](https://www.npmjs.com/package/@shkumbinhsn/try-catch)
|
|
3
|
-
[](https://www.npmjs.com/package/@shkumbinhsn/try-catch)
|
|
4
|
-
# Type-Safe Try-Catch Pattern for TypeScript
|
|
5
|
-
|
|
6
|
-
A lightweight TypeScript utility that provides type-safe error handling through a functional approach. This library allows you to explicitly define error types while maintaining full TypeScript inference and zero runtime overhead.
|
|
7
|
-
|
|
8
|
-
## Installation
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install @shkumbinhsn/try-catch
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Key Features
|
|
15
|
-
|
|
16
|
-
- **🔒 Type Safety**: Explicitly declare what errors your functions can throw
|
|
17
|
-
- **🎯 Zero Runtime Overhead**: Types are compile-time only using TypeScript's structural typing
|
|
18
|
-
- **🔄 Async/Sync Support**: Works seamlessly with both synchronous and asynchronous functions
|
|
19
|
-
- **📦 Lightweight**: Minimal footprint with no dependencies
|
|
20
|
-
- **🧠 Smart Inference**: Falls back to standard TypeScript inference when no error types are specified
|
|
21
|
-
- **🛡️ Tuple-based**: Returns `[data, error]` tuples for explicit error handling
|
|
22
|
-
|
|
23
|
-
## Why Use This Pattern?
|
|
24
|
-
|
|
25
|
-
Traditional try-catch blocks in TypeScript don't provide type information about what errors might be thrown. This library solves that by:
|
|
26
|
-
|
|
27
|
-
1. Making error types explicit in function signatures
|
|
28
|
-
2. Forcing explicit error handling through tuple destructuring
|
|
29
|
-
3. Providing better IntelliSense and type checking
|
|
30
|
-
4. Maintaining compatibility with existing code
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Example Code
|
|
35
|
-
|
|
36
|
-
### Defining a Function with Error Handling
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
import { tryCatch, type Throws } from "@shkumbinhsn/try-catch";
|
|
40
|
-
|
|
41
|
-
class CustomError extends Error {}
|
|
42
|
-
|
|
43
|
-
function iMightFail(): string & Throws<CustomError> {
|
|
44
|
-
const random = Math.random();
|
|
45
|
-
if (random > 0.2) {
|
|
46
|
-
return "success";
|
|
47
|
-
} else if (random > 0.5) {
|
|
48
|
-
throw new CustomError("Something went wrong");
|
|
49
|
-
}
|
|
50
|
-
throw new Error("Generic error");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const [data, error] = tryCatch(() => iMightFail());
|
|
54
|
-
|
|
55
|
-
if (error) {
|
|
56
|
-
console.log("Operation failed:", error.message);
|
|
57
|
-
// TypeScript knows: error is Error | CustomError
|
|
58
|
-
} else {
|
|
59
|
-
console.log("Operation succeeded:", data);
|
|
60
|
-
// TypeScript knows: data is string
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Async Functions with Errors
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
async function fetchUserData(id: string): Promise<User & Throws<ValidationError | NetworkError>> {
|
|
68
|
-
if (!id) {
|
|
69
|
-
throw new ValidationError("User ID is required");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const response = await fetch(`/api/users/${id}`);
|
|
73
|
-
if (!response.ok) {
|
|
74
|
-
throw new NetworkError("Failed to fetch user data");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return response.json();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const [userData, error] = await tryCatch(() => fetchUserData("123"));
|
|
81
|
-
|
|
82
|
-
if (error) {
|
|
83
|
-
if (error instanceof ValidationError) {
|
|
84
|
-
console.log("Validation error:", error.message);
|
|
85
|
-
} else if (error instanceof NetworkError) {
|
|
86
|
-
console.log("Network error:", error.message);
|
|
87
|
-
} else {
|
|
88
|
-
console.log("Unexpected error:", error.message);
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
console.log("User data:", userData);
|
|
92
|
-
// TypeScript knows: userData is User
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Without Explicit Error Types
|
|
97
|
-
|
|
98
|
-
When you don't specify error types, the library falls back to standard TypeScript inference:
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
function regularFunction() {
|
|
102
|
-
return "success";
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const [data, error] = tryCatch(regularFunction);
|
|
106
|
-
|
|
107
|
-
if (error) {
|
|
108
|
-
console.log("Operation failed:", error.message);
|
|
109
|
-
// TypeScript knows: error is Error
|
|
110
|
-
} else {
|
|
111
|
-
console.log("Operation succeeded:", data);
|
|
112
|
-
// TypeScript knows: data is string
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## API Reference
|
|
117
|
-
|
|
118
|
-
### `tryCatch<T>(fn: () => T): TryCatchReturn<T>`
|
|
119
|
-
|
|
120
|
-
Executes a function within a try-catch block and returns a result tuple.
|
|
121
|
-
|
|
122
|
-
**Parameters:**
|
|
123
|
-
- `fn`: Function to execute (can be sync or async)
|
|
124
|
-
|
|
125
|
-
**Returns:**
|
|
126
|
-
- `[data, null]` on success
|
|
127
|
-
- `[null, error]` on failure
|
|
128
|
-
|
|
129
|
-
### `Throws<T extends Error>`
|
|
130
|
-
|
|
131
|
-
Type utility for declaring error types in function signatures.
|
|
132
|
-
|
|
133
|
-
**Usage:**
|
|
134
|
-
```typescript
|
|
135
|
-
function myFunction(): ReturnType & Throws<MyError> {
|
|
136
|
-
// function implementation
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Limitations
|
|
141
|
-
|
|
142
|
-
- **Duplicate Definitions**: Error types must be declared in both the throw statement and return type
|
|
143
|
-
- **Runtime Validation**: No runtime enforcement of declared error types
|
|
144
|
-
- **Learning Curve**: Requires understanding of TypeScript's structural typing
|
|
145
|
-
|
|
146
|
-
## Contributing
|
|
147
|
-
|
|
148
|
-
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
149
|
-
|
|
150
|
-
## License
|
|
151
|
-
|
|
152
|
-
MIT
|
package/lib/try-catch.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const errorSymbol = Symbol();
|
|
2
|
-
|
|
3
|
-
type ErrorSymbol = typeof errorSymbol;
|
|
4
|
-
|
|
5
|
-
export type Throws<T extends Error> = {
|
|
6
|
-
[errorSymbol]?: T
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
type ExtractErrors<T> = T extends Throws<infer E> ? E : never;
|
|
10
|
-
|
|
11
|
-
type StripThrows<T> = T extends infer R & Throws<Error> ? R : T;
|
|
12
|
-
|
|
13
|
-
type DataError<T> = [StripThrows<T>, null] | [null, Error | ExtractErrors<T>];
|
|
14
|
-
|
|
15
|
-
type TryCatchReturn<T> = T extends Promise<infer R>
|
|
16
|
-
? Promise<DataError<R>>
|
|
17
|
-
: DataError<T>;
|
|
18
|
-
|
|
19
|
-
export declare function tryCatch<T>(fn: () => T): TryCatchReturn<T>;
|
package/lib/try-catch.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Executes a function within a try-catch block and returns a tuple [data, error].
|
|
3
|
-
*
|
|
4
|
-
* @param {Function} fn - The function to execute. Can be synchronous or return a Promise.
|
|
5
|
-
* @returns {Array|Promise<Array>} A tuple where:
|
|
6
|
-
* - For success: [data, null] where data is the function's return value
|
|
7
|
-
* - For failure: [null, error] where error is the caught exception
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* // Synchronous usage
|
|
11
|
-
* const [data, error] = tryCatch(() => riskyFunction());
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* // Asynchronous usage
|
|
15
|
-
* const [data, error] = await tryCatch(() => asyncRiskyFunction());
|
|
16
|
-
*/
|
|
17
|
-
export function tryCatch(fn) {
|
|
18
|
-
try {
|
|
19
|
-
const result = fn();
|
|
20
|
-
if(result instanceof Promise) {
|
|
21
|
-
return new Promise((resolve) => {
|
|
22
|
-
result.then((data) => resolve([data, null])).catch((error) => resolve([null, error]))
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
return [result, null];
|
|
26
|
-
} catch (e) {
|
|
27
|
-
return [null, e]
|
|
28
|
-
}
|
|
29
|
-
}
|