@mkvlrn/result 3.0.0 → 4.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/README.md +13 -13
- package/build/index.d.ts +18 -1
- package/build/index.js +4 -11
- package/package.json +3 -3
- package/build/index.test.d.ts +0 -1
- package/build/index.test.js +0 -53
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mkvlrn/result
|
|
2
2
|
|
|
3
|
-
Type-safe Result pattern for TypeScript representing success or
|
|
3
|
+
Type-safe Result pattern for TypeScript representing success or error. Anything to avoid try/catch hell.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -11,16 +11,16 @@ npm add @mkvlrn/result
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { Result } from "@mkvlrn/result";
|
|
14
|
+
import { Result, AsyncResult, R } from "@mkvlrn/result";
|
|
15
15
|
|
|
16
16
|
// Success
|
|
17
|
-
const success =
|
|
17
|
+
const success = R.ok(42);
|
|
18
18
|
|
|
19
19
|
// Error
|
|
20
|
-
const failure =
|
|
20
|
+
const failure = R.error(new Error("Something went wrong"));
|
|
21
21
|
|
|
22
22
|
// Check result
|
|
23
|
-
const result =
|
|
23
|
+
const result = R.ok(42);
|
|
24
24
|
if (result.error) {
|
|
25
25
|
console.log("Error:", result.error.message);
|
|
26
26
|
} else {
|
|
@@ -35,9 +35,9 @@ if (result.error) {
|
|
|
35
35
|
```typescript
|
|
36
36
|
function divide(a: number, b: number): Result<number, Error> {
|
|
37
37
|
if (b === 0) {
|
|
38
|
-
return
|
|
38
|
+
return R.error(new Error("Division by zero"));
|
|
39
39
|
}
|
|
40
|
-
return
|
|
40
|
+
return R.ok(a / b);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const result = divide(10, 2);
|
|
@@ -49,16 +49,16 @@ if (!result.error) {
|
|
|
49
49
|
### Async Operations
|
|
50
50
|
|
|
51
51
|
```typescript
|
|
52
|
-
async function fetchUser(id: number):
|
|
52
|
+
async function fetchUser(id: number): AsyncResult<User, Error> {
|
|
53
53
|
try {
|
|
54
54
|
const response = await fetch(`/api/users/${id}`);
|
|
55
55
|
if (!response.ok) {
|
|
56
|
-
return
|
|
56
|
+
return R.error(new Error(`HTTP ${response.status}`));
|
|
57
57
|
}
|
|
58
58
|
const user = await response.json();
|
|
59
|
-
return
|
|
59
|
+
return R.ok(user);
|
|
60
60
|
} catch (error) {
|
|
61
|
-
return
|
|
61
|
+
return R.error(error instanceof Error ? error : new Error("Unknown error"));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
```
|
|
@@ -71,7 +71,7 @@ class ValidationError extends Error {
|
|
|
71
71
|
|
|
72
72
|
constructor(customField: number, message: string) {
|
|
73
73
|
super(message);
|
|
74
|
-
this.name = "
|
|
74
|
+
this.name = "ValidationError";
|
|
75
75
|
this.customField = customField;
|
|
76
76
|
}
|
|
77
77
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -12,7 +12,24 @@ export type Result<T, E extends Error> = {
|
|
|
12
12
|
} | {
|
|
13
13
|
readonly error: E;
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Async version of Result type that wraps a Result in a Promise.
|
|
17
|
+
*/
|
|
18
|
+
export type AsyncResult<T, E extends Error> = Promise<Result<T, E>>;
|
|
19
|
+
/**
|
|
20
|
+
* Result utility functions for creating Result objects.
|
|
21
|
+
*/
|
|
22
|
+
export declare const R: {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a successful Result with the given value.
|
|
25
|
+
* @param value The success value
|
|
26
|
+
* @returns A Result object representing success
|
|
27
|
+
*/
|
|
16
28
|
ok<T>(value: T): Result<T, never>;
|
|
29
|
+
/**
|
|
30
|
+
* Creates an error Result with the given error.
|
|
31
|
+
* @param error The error value
|
|
32
|
+
* @returns A Result object representing error
|
|
33
|
+
*/
|
|
17
34
|
error<E extends Error>(error: E): Result<never, E>;
|
|
18
35
|
};
|
package/build/index.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* @returns A Result object representing success
|
|
6
|
-
*/
|
|
1
|
+
/**
|
|
2
|
+
* Result utility functions for creating Result objects.
|
|
3
|
+
*/
|
|
4
|
+
export const R = {
|
|
7
5
|
ok: (value) => ({ error: undefined, value }),
|
|
8
|
-
/**
|
|
9
|
-
* Creates an error Result with the given error.
|
|
10
|
-
* @param error The error value
|
|
11
|
-
* @returns A Result object representing error
|
|
12
|
-
*/
|
|
13
6
|
error: (error) => ({ error }),
|
|
14
7
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mkvlrn/result",
|
|
3
3
|
"description": "Result type for TypeScript",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"publishConfig": {
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"build": "rm -rf build && tsc"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@biomejs/biome": "^2.1.
|
|
24
|
-
"@types/node": "^24.0
|
|
23
|
+
"@biomejs/biome": "^2.1.3",
|
|
24
|
+
"@types/node": "^24.1.0",
|
|
25
25
|
"typescript": "^5.8.3",
|
|
26
26
|
"vitest": "^3.2.4"
|
|
27
27
|
}
|
package/build/index.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/build/index.test.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// biome-ignore lint/correctness/noNodejsModules: need the timer
|
|
2
|
-
import { setTimeout } from "node:timers/promises";
|
|
3
|
-
import { assert, describe, it } from "vitest";
|
|
4
|
-
import { Result } from "./index.js";
|
|
5
|
-
class CustomError extends Error {
|
|
6
|
-
customField;
|
|
7
|
-
constructor(customField, message) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = "CustomField";
|
|
10
|
-
this.customField = customField;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
function division(a, b) {
|
|
14
|
-
if (b === 0) {
|
|
15
|
-
return Result.error(new Error("cannot divide by zero"));
|
|
16
|
-
}
|
|
17
|
-
return Result.ok(a / b);
|
|
18
|
-
}
|
|
19
|
-
async function longRunning(shouldFail) {
|
|
20
|
-
await setTimeout(1);
|
|
21
|
-
return shouldFail ? Result.error(new CustomError(42, "wrong")) : Result.ok(3);
|
|
22
|
-
}
|
|
23
|
-
describe("creates a valid result", () => {
|
|
24
|
-
describe("default Error type", () => {
|
|
25
|
-
it("ok result", () => {
|
|
26
|
-
const result = division(4, 2);
|
|
27
|
-
assert.isUndefined(result.error);
|
|
28
|
-
assert.isDefined(result.value);
|
|
29
|
-
assert.strictEqual(result.value, 2);
|
|
30
|
-
});
|
|
31
|
-
it("error result", () => {
|
|
32
|
-
const result = division(4, 0);
|
|
33
|
-
assert.isDefined(result.error);
|
|
34
|
-
assert.instanceOf(result.error, Error);
|
|
35
|
-
assert.strictEqual(result.error.message, "cannot divide by zero");
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe("custom error", () => {
|
|
39
|
-
it("ok result", async () => {
|
|
40
|
-
const result = await longRunning(false);
|
|
41
|
-
assert.isUndefined(result.error);
|
|
42
|
-
assert.isDefined(result.value);
|
|
43
|
-
assert.strictEqual(result.value, 3);
|
|
44
|
-
});
|
|
45
|
-
it("error result", async () => {
|
|
46
|
-
const result = await longRunning(true);
|
|
47
|
-
assert.isDefined(result.error);
|
|
48
|
-
assert.instanceOf(result.error, CustomError);
|
|
49
|
-
assert.strictEqual(result.error.message, "wrong");
|
|
50
|
-
assert.strictEqual(result.error.customField, 42);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
});
|