@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.
@@ -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.3",
4
- "description": "A utility package for handling try-catch blocks in TypeScript.",
5
- "main": "./lib/try-catch.js",
6
- "module": "./lib/try-catch.js",
7
- "types": "./lib/try-catch.d.ts",
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": "./lib/try-catch.d.ts",
11
- "import": "./lib/try-catch.js",
12
- "require": "./lib/try-catch.js"
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.js"
13
13
  }
14
14
  },
15
15
  "files": [
16
- "lib"
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
- "test": "tsc -p tsconfig.json"
26
- },
27
- "repository": {
28
- "type": "git",
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
- "typescript": "^5.0.0"
48
+ "vitest": "^1.2.0"
45
49
  }
46
50
  }
package/README.md DELETED
@@ -1,152 +0,0 @@
1
- ![cowboy trying to catch a horse](https://i.imgur.com/TzMOUUL.jpeg)
2
- [![npm version](https://img.shields.io/npm/v/@shkumbinhsn/try-catch.svg)](https://www.npmjs.com/package/@shkumbinhsn/try-catch)
3
- [![npm downloads](https://img.shields.io/npm/dm/@shkumbinhsn/try-catch.svg)](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
@@ -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
- }