@j2blasco/ts-result 0.1.11 → 0.1.13
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.cjs +23 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/result-functions.d.cts +3 -2
- package/dist/result-functions.d.cts.map +1 -1
- package/dist/result-functions.d.ts +2 -1
- package/dist/result-functions.d.ts.map +1 -1
- package/dist/result-serialization.d.cts +10 -0
- package/dist/result-serialization.d.cts.map +1 -0
- package/dist/result-serialization.d.ts +10 -0
- package/dist/result-serialization.d.ts.map +1 -0
- package/dist/result.d.cts +13 -8
- package/dist/result.d.cts.map +1 -1
- package/dist/result.d.ts +12 -7
- package/dist/result.d.ts.map +1 -1
- package/dist/utils/test/assert-type.d.cts +1 -1
- package/dist/utils/test/assert-type.d.cts.map +1 -1
- package/dist/utils/test/assert-type.d.ts.map +1 -1
- package/package.json +6 -8
- package/src/index.ts +2 -2
- package/src/result-functions.test.ts +32 -20
- package/src/result-functions.ts +17 -11
- package/src/result-serialization.test.ts +18 -0
- package/src/result-serialization.ts +49 -0
- package/src/result.test.ts +28 -3
- package/src/result.ts +51 -20
- package/src/utils/test/assert-type.ts +3 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
resultError: () => resultError,
|
|
31
31
|
resultSuccess: () => resultSuccess,
|
|
32
32
|
resultSuccessVoid: () => resultSuccessVoid,
|
|
33
|
+
unwrapOrThrow: () => unwrapOrThrow,
|
|
33
34
|
unwrapSuccessResult: () => unwrapSuccessResult
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -76,6 +77,15 @@ var ResultSuccessImp = class {
|
|
|
76
77
|
constructor(value) {
|
|
77
78
|
this.value = value;
|
|
78
79
|
}
|
|
80
|
+
getValueUnsafe() {
|
|
81
|
+
return this.value;
|
|
82
|
+
}
|
|
83
|
+
getErrorUnsafe() {
|
|
84
|
+
throw new Error("This result is success, cannot get error");
|
|
85
|
+
}
|
|
86
|
+
isSuccess() {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
79
89
|
andThen(f) {
|
|
80
90
|
return f(this.value);
|
|
81
91
|
}
|
|
@@ -96,6 +106,15 @@ var ResultErrorImp = class {
|
|
|
96
106
|
constructor(error) {
|
|
97
107
|
this.error = error;
|
|
98
108
|
}
|
|
109
|
+
getValueUnsafe() {
|
|
110
|
+
throw new Error("This result is error, cannot get value");
|
|
111
|
+
}
|
|
112
|
+
getErrorUnsafe() {
|
|
113
|
+
return this.error;
|
|
114
|
+
}
|
|
115
|
+
isSuccess() {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
99
118
|
andThen(_f) {
|
|
100
119
|
return this;
|
|
101
120
|
}
|
|
@@ -132,6 +151,9 @@ function catchError(callback) {
|
|
|
132
151
|
function catchErrorAsync(callback) {
|
|
133
152
|
return (result) => result.catchErrorAsync(callback);
|
|
134
153
|
}
|
|
154
|
+
function unwrapOrThrow(result) {
|
|
155
|
+
return result.unwrapOrThrow();
|
|
156
|
+
}
|
|
135
157
|
// Annotate the CommonJS export names for ESM import in node:
|
|
136
158
|
0 && (module.exports = {
|
|
137
159
|
andThen,
|
|
@@ -144,6 +166,7 @@ function catchErrorAsync(callback) {
|
|
|
144
166
|
resultError,
|
|
145
167
|
resultSuccess,
|
|
146
168
|
resultSuccessVoid,
|
|
169
|
+
unwrapOrThrow,
|
|
147
170
|
unwrapSuccessResult
|
|
148
171
|
});
|
|
149
172
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/result.ts","../src/result-functions.ts"],"sourcesContent":["export * from './result';\nexport * from './result-functions';","export interface Result<
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/result.ts","../src/result-functions.ts"],"sourcesContent":["export * from './result.js';\nexport * from './result-functions.js';","export interface Result<TSuccess, TError> {\n isSuccess(): boolean;\n andThen<TResult extends Result<any, any>>(\n f: (value: TSuccess) => TResult,\n ): Result<SuccessType<TResult>, TError | ErrorType<TResult>>;\n andThenAsync<TResult extends Result<any, any>>(\n f: (value: TSuccess) => Promise<TResult>,\n ): Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;\n catchError<TResult extends Result<any, any>>(\n f: (error: TError) => TResult,\n ): Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;\n catchErrorAsync<TResult extends Result<any, any>>(\n f: (error: TError) => Promise<TResult>,\n ): Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;\n unwrapOrThrow(errorCallback?: (e: TError) => void): TSuccess;\n}\n\nexport interface UnsafeResult<TSuccess, TError> extends Result<\n TSuccess,\n TError\n> {\n getValueUnsafe(): TSuccess;\n getErrorUnsafe(): TError;\n}\n\nexport function unwrapSuccessResult<T>(result: Result<T, never>): T {\n if (result instanceof ResultSuccessImp) {\n return result[\"value\"];\n }\n throw new Error(\"Unreachable code. Result is an error\");\n}\n\nexport type ErrorWithCode<TCode, TData = object> = { code: TCode; data: TData };\nexport function errorWithCode<TCode, TData>(\n code: TCode,\n data: TData,\n): ErrorWithCode<TCode, TData> {\n return {\n code,\n data,\n };\n}\n\nexport type ErrorUnknown = {\n code: \"unknown\";\n data: { message: string };\n};\nexport function errorUnkown(message: string): ErrorUnknown {\n return {\n code: \"unknown\",\n data: { message },\n };\n}\n\nexport type SuccessType<T> = T extends Result<infer S, any> ? S : never;\nexport type ErrorType<T> = T extends Result<any, infer E> ? E : never;\n\nexport type SuccessVoid = never;\n\nexport function resultSuccessVoid(): Result<SuccessVoid, never> {\n return new ResultSuccessImp<SuccessVoid>(undefined as never);\n}\n\nexport function resultSuccess<TSuccess1>(\n value: TSuccess1,\n): Result<TSuccess1, never> {\n return new ResultSuccessImp<TSuccess1>(value);\n}\n\ntype EnforceLiteral<T> = string extends T ? never : T;\n\nexport class resultError {\n public static unknown(message: string): Result<never, ErrorUnknown> {\n return new ResultErrorImp<ErrorUnknown>(errorUnkown(message));\n }\n public static withCode<TCode, TData = object>(\n code: EnforceLiteral<TCode>,\n data: TData = {} as TData,\n ): Result<never, ErrorWithCode<TCode, TData>> {\n return new ResultErrorImp<ErrorWithCode<TCode, TData>>(\n errorWithCode(code, data),\n );\n }\n public static fromError<TError1 extends ErrorWithCode<any, object>>(\n error: TError1,\n ): Result<never, TError1> {\n return new ResultErrorImp<TError1>(error);\n }\n}\n\nclass ResultSuccessImp<TSuccess1> implements UnsafeResult<TSuccess1, never> {\n constructor(private value: TSuccess1) {}\n\n public getValueUnsafe(): TSuccess1 {\n return this.value;\n }\n public getErrorUnsafe(): never {\n throw new Error(\"This result is success, cannot get error\");\n }\n\n public isSuccess() {\n return true;\n }\n\n public andThen<TSuccess2, TError2>(\n f: (value: TSuccess1) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError2> {\n return f(this.value);\n }\n\n public async andThenAsync<TSuccess2, TError2>(\n f: (value: TSuccess1) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError2>> {\n return await f(this.value);\n }\n\n public catchError<TSuccess2, TError2>(\n _f: (error: never) => Result<TSuccess2, TError2>,\n ): Result<TSuccess1 | TSuccess2, TError2> {\n return this;\n }\n\n public async catchErrorAsync<TSuccess2, TError2>(\n _f: (error: never) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess1 | TSuccess2, TError2>> {\n return this;\n }\n\n public unwrapOrThrow(_errorCallback?: (e: never) => void): TSuccess1 {\n return this.value;\n }\n}\n\nclass ResultErrorImp<TError1> implements UnsafeResult<never, TError1> {\n constructor(private error: TError1) {}\n\n public getValueUnsafe(): never {\n throw new Error(\"This result is error, cannot get value\");\n }\n public getErrorUnsafe(): TError1 {\n return this.error;\n }\n\n public isSuccess(): boolean {\n return false;\n }\n\n public andThen<TSuccess2, TError2>(\n _f: (value: never) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError1 | TError2> {\n return this;\n }\n\n public async andThenAsync<TSuccess2, TError2>(\n _f: (value: never) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError1 | TError2>> {\n return this;\n }\n\n public catchError<TSuccess2, TError2>(\n f: (error: TError1) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError2> {\n return f(this.error);\n }\n\n public async catchErrorAsync<TSuccess2, TError2>(\n f: (error: TError1) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError2>> {\n return await f(this.error);\n }\n\n public unwrapOrThrow(errorCallback?: (e: TError1) => void): never {\n if (errorCallback !== undefined) {\n errorCallback(this.error);\n }\n throw this.error;\n }\n}\n\nexport type UnwrapErrorFromResult<T> =\n T extends Result<any, infer U> ? U : never;\n\nexport function makeSafePromise<T>(\n promise: Promise<T>,\n): Promise<Result<T, ErrorUnknown>> {\n return promise\n .then((value) => resultSuccess(value))\n .catch((error) => resultError.unknown(error.message));\n}\n","import { ErrorType, Result, SuccessType } from \"./result.js\";\n\nexport function andThen<TSuccess, TError, TResult extends Result<any, any>>(\n callback: (value: TSuccess) => TResult,\n): (\n result: Result<TSuccess, TError>,\n) => Result<SuccessType<TResult>, TError | ErrorType<TResult>> {\n return (result) => result.andThen(callback);\n}\n\nexport function andThenAsync<\n TSuccess,\n TError,\n TResult extends Result<any, any>,\n>(\n callback: (value: TSuccess) => Promise<TResult>,\n): (\n result: Result<TSuccess, TError>,\n) => Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>> {\n return (result) => result.andThenAsync(callback);\n}\n\nexport function catchError<TSuccess, TError, TResult extends Result<any, any>>(\n callback: (error: TError) => TResult,\n): (\n result: Result<TSuccess, TError>,\n) => Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>> {\n return (result) => result.catchError(callback);\n}\n\nexport function catchErrorAsync<\n TSuccess,\n TError,\n TResult extends Result<any, any>,\n>(\n callback: (error: TError) => Promise<TResult>,\n): (\n result: Result<TSuccess, TError>,\n) => Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>> {\n return (result) => result.catchErrorAsync(callback);\n}\n\nexport function unwrapOrThrow<TSuccess>(\n result: Result<TSuccess, never>,\n): TSuccess {\n return result.unwrapOrThrow();\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './result';
|
|
2
|
-
export * from './result-functions';
|
|
3
|
-
//# sourceMappingURL=index.d.
|
|
1
|
+
export * from './result.js';
|
|
2
|
+
export * from './result-functions.js';
|
|
3
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './result';
|
|
2
|
-
export * from './result-functions';
|
|
1
|
+
export * from './result.js';
|
|
2
|
+
export * from './result-functions.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,15 @@ var ResultSuccessImp = class {
|
|
|
40
40
|
constructor(value) {
|
|
41
41
|
this.value = value;
|
|
42
42
|
}
|
|
43
|
+
getValueUnsafe() {
|
|
44
|
+
return this.value;
|
|
45
|
+
}
|
|
46
|
+
getErrorUnsafe() {
|
|
47
|
+
throw new Error("This result is success, cannot get error");
|
|
48
|
+
}
|
|
49
|
+
isSuccess() {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
43
52
|
andThen(f) {
|
|
44
53
|
return f(this.value);
|
|
45
54
|
}
|
|
@@ -60,6 +69,15 @@ var ResultErrorImp = class {
|
|
|
60
69
|
constructor(error) {
|
|
61
70
|
this.error = error;
|
|
62
71
|
}
|
|
72
|
+
getValueUnsafe() {
|
|
73
|
+
throw new Error("This result is error, cannot get value");
|
|
74
|
+
}
|
|
75
|
+
getErrorUnsafe() {
|
|
76
|
+
return this.error;
|
|
77
|
+
}
|
|
78
|
+
isSuccess() {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
63
81
|
andThen(_f) {
|
|
64
82
|
return this;
|
|
65
83
|
}
|
|
@@ -96,6 +114,9 @@ function catchError(callback) {
|
|
|
96
114
|
function catchErrorAsync(callback) {
|
|
97
115
|
return (result) => result.catchErrorAsync(callback);
|
|
98
116
|
}
|
|
117
|
+
function unwrapOrThrow(result) {
|
|
118
|
+
return result.unwrapOrThrow();
|
|
119
|
+
}
|
|
99
120
|
export {
|
|
100
121
|
andThen,
|
|
101
122
|
andThenAsync,
|
|
@@ -107,6 +128,7 @@ export {
|
|
|
107
128
|
resultError,
|
|
108
129
|
resultSuccess,
|
|
109
130
|
resultSuccessVoid,
|
|
131
|
+
unwrapOrThrow,
|
|
110
132
|
unwrapSuccessResult
|
|
111
133
|
};
|
|
112
134
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/result.ts","../src/result-functions.ts"],"sourcesContent":["export interface Result<
|
|
1
|
+
{"version":3,"sources":["../src/result.ts","../src/result-functions.ts"],"sourcesContent":["export interface Result<TSuccess, TError> {\n isSuccess(): boolean;\n andThen<TResult extends Result<any, any>>(\n f: (value: TSuccess) => TResult,\n ): Result<SuccessType<TResult>, TError | ErrorType<TResult>>;\n andThenAsync<TResult extends Result<any, any>>(\n f: (value: TSuccess) => Promise<TResult>,\n ): Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;\n catchError<TResult extends Result<any, any>>(\n f: (error: TError) => TResult,\n ): Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;\n catchErrorAsync<TResult extends Result<any, any>>(\n f: (error: TError) => Promise<TResult>,\n ): Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;\n unwrapOrThrow(errorCallback?: (e: TError) => void): TSuccess;\n}\n\nexport interface UnsafeResult<TSuccess, TError> extends Result<\n TSuccess,\n TError\n> {\n getValueUnsafe(): TSuccess;\n getErrorUnsafe(): TError;\n}\n\nexport function unwrapSuccessResult<T>(result: Result<T, never>): T {\n if (result instanceof ResultSuccessImp) {\n return result[\"value\"];\n }\n throw new Error(\"Unreachable code. Result is an error\");\n}\n\nexport type ErrorWithCode<TCode, TData = object> = { code: TCode; data: TData };\nexport function errorWithCode<TCode, TData>(\n code: TCode,\n data: TData,\n): ErrorWithCode<TCode, TData> {\n return {\n code,\n data,\n };\n}\n\nexport type ErrorUnknown = {\n code: \"unknown\";\n data: { message: string };\n};\nexport function errorUnkown(message: string): ErrorUnknown {\n return {\n code: \"unknown\",\n data: { message },\n };\n}\n\nexport type SuccessType<T> = T extends Result<infer S, any> ? S : never;\nexport type ErrorType<T> = T extends Result<any, infer E> ? E : never;\n\nexport type SuccessVoid = never;\n\nexport function resultSuccessVoid(): Result<SuccessVoid, never> {\n return new ResultSuccessImp<SuccessVoid>(undefined as never);\n}\n\nexport function resultSuccess<TSuccess1>(\n value: TSuccess1,\n): Result<TSuccess1, never> {\n return new ResultSuccessImp<TSuccess1>(value);\n}\n\ntype EnforceLiteral<T> = string extends T ? never : T;\n\nexport class resultError {\n public static unknown(message: string): Result<never, ErrorUnknown> {\n return new ResultErrorImp<ErrorUnknown>(errorUnkown(message));\n }\n public static withCode<TCode, TData = object>(\n code: EnforceLiteral<TCode>,\n data: TData = {} as TData,\n ): Result<never, ErrorWithCode<TCode, TData>> {\n return new ResultErrorImp<ErrorWithCode<TCode, TData>>(\n errorWithCode(code, data),\n );\n }\n public static fromError<TError1 extends ErrorWithCode<any, object>>(\n error: TError1,\n ): Result<never, TError1> {\n return new ResultErrorImp<TError1>(error);\n }\n}\n\nclass ResultSuccessImp<TSuccess1> implements UnsafeResult<TSuccess1, never> {\n constructor(private value: TSuccess1) {}\n\n public getValueUnsafe(): TSuccess1 {\n return this.value;\n }\n public getErrorUnsafe(): never {\n throw new Error(\"This result is success, cannot get error\");\n }\n\n public isSuccess() {\n return true;\n }\n\n public andThen<TSuccess2, TError2>(\n f: (value: TSuccess1) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError2> {\n return f(this.value);\n }\n\n public async andThenAsync<TSuccess2, TError2>(\n f: (value: TSuccess1) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError2>> {\n return await f(this.value);\n }\n\n public catchError<TSuccess2, TError2>(\n _f: (error: never) => Result<TSuccess2, TError2>,\n ): Result<TSuccess1 | TSuccess2, TError2> {\n return this;\n }\n\n public async catchErrorAsync<TSuccess2, TError2>(\n _f: (error: never) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess1 | TSuccess2, TError2>> {\n return this;\n }\n\n public unwrapOrThrow(_errorCallback?: (e: never) => void): TSuccess1 {\n return this.value;\n }\n}\n\nclass ResultErrorImp<TError1> implements UnsafeResult<never, TError1> {\n constructor(private error: TError1) {}\n\n public getValueUnsafe(): never {\n throw new Error(\"This result is error, cannot get value\");\n }\n public getErrorUnsafe(): TError1 {\n return this.error;\n }\n\n public isSuccess(): boolean {\n return false;\n }\n\n public andThen<TSuccess2, TError2>(\n _f: (value: never) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError1 | TError2> {\n return this;\n }\n\n public async andThenAsync<TSuccess2, TError2>(\n _f: (value: never) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError1 | TError2>> {\n return this;\n }\n\n public catchError<TSuccess2, TError2>(\n f: (error: TError1) => Result<TSuccess2, TError2>,\n ): Result<TSuccess2, TError2> {\n return f(this.error);\n }\n\n public async catchErrorAsync<TSuccess2, TError2>(\n f: (error: TError1) => Promise<Result<TSuccess2, TError2>>,\n ): Promise<Result<TSuccess2, TError2>> {\n return await f(this.error);\n }\n\n public unwrapOrThrow(errorCallback?: (e: TError1) => void): never {\n if (errorCallback !== undefined) {\n errorCallback(this.error);\n }\n throw this.error;\n }\n}\n\nexport type UnwrapErrorFromResult<T> =\n T extends Result<any, infer U> ? U : never;\n\nexport function makeSafePromise<T>(\n promise: Promise<T>,\n): Promise<Result<T, ErrorUnknown>> {\n return promise\n .then((value) => resultSuccess(value))\n .catch((error) => resultError.unknown(error.message));\n}\n","import { ErrorType, Result, SuccessType } from \"./result.js\";\n\nexport function andThen<TSuccess, TError, TResult extends Result<any, any>>(\n callback: (value: TSuccess) => TResult,\n): (\n result: Result<TSuccess, TError>,\n) => Result<SuccessType<TResult>, TError | ErrorType<TResult>> {\n return (result) => result.andThen(callback);\n}\n\nexport function andThenAsync<\n TSuccess,\n TError,\n TResult extends Result<any, any>,\n>(\n callback: (value: TSuccess) => Promise<TResult>,\n): (\n result: Result<TSuccess, TError>,\n) => Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>> {\n return (result) => result.andThenAsync(callback);\n}\n\nexport function catchError<TSuccess, TError, TResult extends Result<any, any>>(\n callback: (error: TError) => TResult,\n): (\n result: Result<TSuccess, TError>,\n) => Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>> {\n return (result) => result.catchError(callback);\n}\n\nexport function catchErrorAsync<\n TSuccess,\n TError,\n TResult extends Result<any, any>,\n>(\n callback: (error: TError) => Promise<TResult>,\n): (\n result: Result<TSuccess, TError>,\n) => Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>> {\n return (result) => result.catchErrorAsync(callback);\n}\n\nexport function unwrapOrThrow<TSuccess>(\n result: Result<TSuccess, never>,\n): TSuccess {\n return result.unwrapOrThrow();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ErrorType, Result, SuccessType } from "./result";
|
|
1
|
+
import { ErrorType, Result, SuccessType } from "./result.js";
|
|
2
2
|
export declare function andThen<TSuccess, TError, TResult extends Result<any, any>>(callback: (value: TSuccess) => TResult): (result: Result<TSuccess, TError>) => Result<SuccessType<TResult>, TError | ErrorType<TResult>>;
|
|
3
3
|
export declare function andThenAsync<TSuccess, TError, TResult extends Result<any, any>>(callback: (value: TSuccess) => Promise<TResult>): (result: Result<TSuccess, TError>) => Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;
|
|
4
4
|
export declare function catchError<TSuccess, TError, TResult extends Result<any, any>>(callback: (error: TError) => TResult): (result: Result<TSuccess, TError>) => Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;
|
|
5
5
|
export declare function catchErrorAsync<TSuccess, TError, TResult extends Result<any, any>>(callback: (error: TError) => Promise<TResult>): (result: Result<TSuccess, TError>) => Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;
|
|
6
|
-
|
|
6
|
+
export declare function unwrapOrThrow<TSuccess>(result: Result<TSuccess, never>): TSuccess;
|
|
7
|
+
//# sourceMappingURL=result-functions.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result-functions.d.ts","sourceRoot":"","sources":["../src/result-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"result-functions.d.ts","sourceRoot":"","sources":["../src/result-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACxE,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,GACrC,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAE7D;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EACR,MAAM,EACN,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAEhC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,GAC9C,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAEtE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC3E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GACnC,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAE/D;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EACR,MAAM,EACN,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAEhC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC5C,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAExE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EACpC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,GAC9B,QAAQ,CAEV"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ErrorType, Result, SuccessType } from "./result";
|
|
1
|
+
import { ErrorType, Result, SuccessType } from "./result.js";
|
|
2
2
|
export declare function andThen<TSuccess, TError, TResult extends Result<any, any>>(callback: (value: TSuccess) => TResult): (result: Result<TSuccess, TError>) => Result<SuccessType<TResult>, TError | ErrorType<TResult>>;
|
|
3
3
|
export declare function andThenAsync<TSuccess, TError, TResult extends Result<any, any>>(callback: (value: TSuccess) => Promise<TResult>): (result: Result<TSuccess, TError>) => Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;
|
|
4
4
|
export declare function catchError<TSuccess, TError, TResult extends Result<any, any>>(callback: (error: TError) => TResult): (result: Result<TSuccess, TError>) => Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;
|
|
5
5
|
export declare function catchErrorAsync<TSuccess, TError, TResult extends Result<any, any>>(callback: (error: TError) => Promise<TResult>): (result: Result<TSuccess, TError>) => Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;
|
|
6
|
+
export declare function unwrapOrThrow<TSuccess>(result: Result<TSuccess, never>): TSuccess;
|
|
6
7
|
//# sourceMappingURL=result-functions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result-functions.d.ts","sourceRoot":"","sources":["../src/result-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"result-functions.d.ts","sourceRoot":"","sources":["../src/result-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACxE,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,GACrC,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAE7D;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EACR,MAAM,EACN,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAEhC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,GAC9C,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAEtE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC3E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GACnC,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAE/D;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EACR,MAAM,EACN,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAEhC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC5C,CACD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAExE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EACpC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,GAC9B,QAAQ,CAEV"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Result } from "./result.js";
|
|
2
|
+
type SerializedResult = {
|
|
3
|
+
type: "ts-result";
|
|
4
|
+
isSuccess: boolean;
|
|
5
|
+
data: any;
|
|
6
|
+
};
|
|
7
|
+
export declare function serializeResult<TSuccess, TError>(value: Result<TSuccess, TError>): SerializedResult;
|
|
8
|
+
export declare function deserializeResult(value: unknown): Result<any, never> | Result<never, any>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=result-serialization.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-serialization.d.ts","sourceRoot":"","sources":["../src/result-serialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA4C,MAAM,aAAa,CAAC;AAE/E,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAC9C,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC9B,gBAAgB,CAelB;AAWD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,2CAY/C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Result } from "./result.js";
|
|
2
|
+
type SerializedResult = {
|
|
3
|
+
type: "ts-result";
|
|
4
|
+
isSuccess: boolean;
|
|
5
|
+
data: any;
|
|
6
|
+
};
|
|
7
|
+
export declare function serializeResult<TSuccess, TError>(value: Result<TSuccess, TError>): SerializedResult;
|
|
8
|
+
export declare function deserializeResult(value: unknown): Result<any, never> | Result<never, any>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=result-serialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-serialization.d.ts","sourceRoot":"","sources":["../src/result-serialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA4C,MAAM,aAAa,CAAC;AAE/E,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAC9C,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC9B,gBAAgB,CAelB;AAWD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,2CAY/C"}
|
package/dist/result.d.cts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
export interface Result<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export interface Result<TSuccess, TError> {
|
|
2
|
+
isSuccess(): boolean;
|
|
3
|
+
andThen<TResult extends Result<any, any>>(f: (value: TSuccess) => TResult): Result<SuccessType<TResult>, TError | ErrorType<TResult>>;
|
|
4
|
+
andThenAsync<TResult extends Result<any, any>>(f: (value: TSuccess) => Promise<TResult>): Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;
|
|
5
|
+
catchError<TResult extends Result<any, any>>(f: (error: TError) => TResult): Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;
|
|
6
|
+
catchErrorAsync<TResult extends Result<any, any>>(f: (error: TError) => Promise<TResult>): Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;
|
|
7
|
+
unwrapOrThrow(errorCallback?: (e: TError) => void): TSuccess;
|
|
8
|
+
}
|
|
9
|
+
export interface UnsafeResult<TSuccess, TError> extends Result<TSuccess, TError> {
|
|
10
|
+
getValueUnsafe(): TSuccess;
|
|
11
|
+
getErrorUnsafe(): TError;
|
|
7
12
|
}
|
|
8
13
|
export declare function unwrapSuccessResult<T>(result: Result<T, never>): T;
|
|
9
14
|
export type ErrorWithCode<TCode, TData = object> = {
|
|
@@ -12,7 +17,7 @@ export type ErrorWithCode<TCode, TData = object> = {
|
|
|
12
17
|
};
|
|
13
18
|
export declare function errorWithCode<TCode, TData>(code: TCode, data: TData): ErrorWithCode<TCode, TData>;
|
|
14
19
|
export type ErrorUnknown = {
|
|
15
|
-
code:
|
|
20
|
+
code: "unknown";
|
|
16
21
|
data: {
|
|
17
22
|
message: string;
|
|
18
23
|
};
|
|
@@ -32,4 +37,4 @@ export declare class resultError {
|
|
|
32
37
|
export type UnwrapErrorFromResult<T> = T extends Result<any, infer U> ? U : never;
|
|
33
38
|
export declare function makeSafePromise<T>(promise: Promise<T>): Promise<Result<T, ErrorUnknown>>;
|
|
34
39
|
export {};
|
|
35
|
-
//# sourceMappingURL=result.d.
|
|
40
|
+
//# sourceMappingURL=result.d.cts.map
|
package/dist/result.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM,CAAC,QAAQ,EAAE,MAAM;IACtC,SAAS,IAAI,OAAO,CAAC;IACrB,OAAO,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACtC,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,GAC9B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D,YAAY,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC3C,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,UAAU,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACzC,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAC5B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC9C,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxE,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,QAAQ,CAAC;CAC9D;AAED,MAAM,WAAW,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAE,SAAQ,MAAM,CAC5D,QAAQ,EACR,MAAM,CACP;IACC,cAAc,IAAI,QAAQ,CAAC;IAC3B,cAAc,IAAI,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAKlE;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,IAAI;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAChF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EACxC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,KAAK,GACV,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAK7B;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B,CAAC;AACF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAKzD;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACxE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC;AAEhC,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAE9D;AAED,wBAAgB,aAAa,CAAC,SAAS,EACrC,KAAK,EAAE,SAAS,GACf,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAE1B;AAED,KAAK,cAAc,CAAC,CAAC,IAAI,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAEtD,qBAAa,WAAW;WACR,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;WAGrD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAC1C,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAC3B,IAAI,GAAE,KAAmB,GACxB,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;WAK/B,SAAS,CAAC,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,EAChE,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;CAG1B;AA2FD,MAAM,MAAM,qBAAqB,CAAC,CAAC,IACjC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7C,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAIlC"}
|
package/dist/result.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
export interface Result<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export interface Result<TSuccess, TError> {
|
|
2
|
+
isSuccess(): boolean;
|
|
3
|
+
andThen<TResult extends Result<any, any>>(f: (value: TSuccess) => TResult): Result<SuccessType<TResult>, TError | ErrorType<TResult>>;
|
|
4
|
+
andThenAsync<TResult extends Result<any, any>>(f: (value: TSuccess) => Promise<TResult>): Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;
|
|
5
|
+
catchError<TResult extends Result<any, any>>(f: (error: TError) => TResult): Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;
|
|
6
|
+
catchErrorAsync<TResult extends Result<any, any>>(f: (error: TError) => Promise<TResult>): Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;
|
|
7
|
+
unwrapOrThrow(errorCallback?: (e: TError) => void): TSuccess;
|
|
8
|
+
}
|
|
9
|
+
export interface UnsafeResult<TSuccess, TError> extends Result<TSuccess, TError> {
|
|
10
|
+
getValueUnsafe(): TSuccess;
|
|
11
|
+
getErrorUnsafe(): TError;
|
|
7
12
|
}
|
|
8
13
|
export declare function unwrapSuccessResult<T>(result: Result<T, never>): T;
|
|
9
14
|
export type ErrorWithCode<TCode, TData = object> = {
|
|
@@ -12,7 +17,7 @@ export type ErrorWithCode<TCode, TData = object> = {
|
|
|
12
17
|
};
|
|
13
18
|
export declare function errorWithCode<TCode, TData>(code: TCode, data: TData): ErrorWithCode<TCode, TData>;
|
|
14
19
|
export type ErrorUnknown = {
|
|
15
|
-
code:
|
|
20
|
+
code: "unknown";
|
|
16
21
|
data: {
|
|
17
22
|
message: string;
|
|
18
23
|
};
|
package/dist/result.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM,CAAC,QAAQ,EAAE,MAAM;IACtC,SAAS,IAAI,OAAO,CAAC;IACrB,OAAO,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACtC,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,GAC9B,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D,YAAY,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC3C,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,UAAU,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EACzC,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAC5B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAC9C,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxE,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,QAAQ,CAAC;CAC9D;AAED,MAAM,WAAW,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAE,SAAQ,MAAM,CAC5D,QAAQ,EACR,MAAM,CACP;IACC,cAAc,IAAI,QAAQ,CAAC;IAC3B,cAAc,IAAI,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAKlE;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,IAAI;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAChF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EACxC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,KAAK,GACV,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAK7B;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B,CAAC;AACF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAKzD;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACxE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC;AAEhC,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAE9D;AAED,wBAAgB,aAAa,CAAC,SAAS,EACrC,KAAK,EAAE,SAAS,GACf,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAE1B;AAED,KAAK,cAAc,CAAC,CAAC,IAAI,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAEtD,qBAAa,WAAW;WACR,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;WAGrD,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAC1C,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAC3B,IAAI,GAAE,KAAmB,GACxB,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;WAK/B,SAAS,CAAC,OAAO,SAAS,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,EAChE,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;CAG1B;AA2FD,MAAM,MAAM,qBAAqB,CAAC,CAAC,IACjC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7C,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAIlC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-type.d.ts","sourceRoot":"","sources":["../../../src/utils/test/assert-type.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assert-type.d.ts","sourceRoot":"","sources":["../../../src/utils/test/assert-type.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,EAC3C,MAAM,EAAE,OAAO,SAAS,SAAS,GAAG,IAAI,GAAG,KAAK,GAC/C,IAAI,CAAG;AAEV,wBAAgB,eAAe,SAE9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert-type.d.ts","sourceRoot":"","sources":["../../../src/utils/test/assert-type.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assert-type.d.ts","sourceRoot":"","sources":["../../../src/utils/test/assert-type.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,EAC3C,MAAM,EAAE,OAAO,SAAS,SAAS,GAAG,IAAI,GAAG,KAAK,GAC/C,IAAI,CAAG;AAEV,wBAAgB,eAAe,SAE9B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j2blasco/ts-result",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Result Monad for TypeScript",
|
|
5
5
|
"author": "j2blasco",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,16 +44,14 @@
|
|
|
44
44
|
"build:dts": "tsc -p tsconfig.build.json && node scripts/build-maps.cjs",
|
|
45
45
|
"clean": "shx rm -rf dist",
|
|
46
46
|
"prepublishOnly": "npm run build",
|
|
47
|
-
"test": "
|
|
47
|
+
"test": "vitest --config=./vitest.config.ts run"
|
|
48
48
|
},
|
|
49
49
|
"type": "module",
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@j2blasco/ts-pipe": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"ts-jest": "^29.3.2",
|
|
56
|
-
"tsup": "^8.5.0",
|
|
51
|
+
"@j2blasco/ts-pipe": "~0.1.6",
|
|
52
|
+
"vitest": "~4.1.5",
|
|
53
|
+
"shx": "~0.4.0",
|
|
54
|
+
"tsup": "~8.5.0",
|
|
57
55
|
"typescript": "~5.7.2"
|
|
58
56
|
}
|
|
59
57
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './result';
|
|
2
|
-
export * from './result-functions';
|
|
1
|
+
export * from './result.js';
|
|
2
|
+
export * from './result-functions.js';
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
andThen,
|
|
3
|
+
andThenAsync,
|
|
4
|
+
catchError,
|
|
5
|
+
catchErrorAsync,
|
|
6
|
+
unwrapOrThrow,
|
|
7
|
+
} from "./result-functions.js";
|
|
8
|
+
import { resultSuccess, resultError, ErrorUnknown, Result } from "./result.js";
|
|
9
|
+
import { assertType } from "./utils/test/assert-type.js";
|
|
10
|
+
import { pipeAsync, pipe } from "@j2blasco/ts-pipe";
|
|
11
|
+
import { describe, expect, test } from "vitest";
|
|
6
12
|
|
|
7
13
|
function doSomething(): Result<string, ErrorUnknown> {
|
|
8
14
|
return resultSuccess("5");
|
|
@@ -26,7 +32,7 @@ describe("Result functions", () => {
|
|
|
26
32
|
test("andThenAsync transforms success values", async () => {
|
|
27
33
|
const result = resultSuccess(5);
|
|
28
34
|
const transformed = await andThenAsync(async (x: number) =>
|
|
29
|
-
resultSuccess(x * 2)
|
|
35
|
+
resultSuccess(x * 2),
|
|
30
36
|
)(result);
|
|
31
37
|
expect(transformed.unwrapOrThrow()).toBe(10);
|
|
32
38
|
});
|
|
@@ -34,7 +40,7 @@ describe("Result functions", () => {
|
|
|
34
40
|
test("andThenAsync preserves failures", async () => {
|
|
35
41
|
const result = resultError.unknown("error message");
|
|
36
42
|
const transformed = await andThenAsync(async (x: any) =>
|
|
37
|
-
resultSuccess(x * 2)
|
|
43
|
+
resultSuccess(x * 2),
|
|
38
44
|
)(result);
|
|
39
45
|
|
|
40
46
|
// Check if the transformation preserves the error by trying to unwrap
|
|
@@ -43,46 +49,52 @@ describe("Result functions", () => {
|
|
|
43
49
|
|
|
44
50
|
test("catchError handles errors", () => {
|
|
45
51
|
const result = resultError.unknown("error message");
|
|
46
|
-
const recovered = catchError((error: ErrorUnknown) =>
|
|
47
|
-
resultSuccess("recovered")
|
|
52
|
+
const recovered = catchError((error: ErrorUnknown) =>
|
|
53
|
+
resultSuccess("recovered"),
|
|
48
54
|
)(result);
|
|
49
55
|
expect(recovered.unwrapOrThrow()).toBe("recovered");
|
|
50
56
|
});
|
|
51
57
|
|
|
52
58
|
test("catchError preserves success values", () => {
|
|
53
59
|
const result = resultSuccess(42);
|
|
54
|
-
const recovered = catchError((error: any) =>
|
|
55
|
-
resultSuccess("should not be called")
|
|
60
|
+
const recovered = catchError((error: any) =>
|
|
61
|
+
resultSuccess("should not be called"),
|
|
56
62
|
)(result);
|
|
57
63
|
expect(recovered.unwrapOrThrow()).toBe(42);
|
|
58
64
|
});
|
|
59
65
|
|
|
60
66
|
test("catchErrorAsync handles errors", async () => {
|
|
61
67
|
const result = resultError.unknown("error message");
|
|
62
|
-
const recovered = await catchErrorAsync(async (error: ErrorUnknown) =>
|
|
63
|
-
resultSuccess("recovered async")
|
|
68
|
+
const recovered = await catchErrorAsync(async (error: ErrorUnknown) =>
|
|
69
|
+
resultSuccess("recovered async"),
|
|
64
70
|
)(result);
|
|
65
71
|
expect(recovered.unwrapOrThrow()).toBe("recovered async");
|
|
66
72
|
});
|
|
67
73
|
|
|
68
74
|
test("catchErrorAsync preserves success values", async () => {
|
|
69
75
|
const result = resultSuccess(42);
|
|
70
|
-
const recovered = await catchErrorAsync(async (error: any) =>
|
|
71
|
-
resultSuccess("should not be called")
|
|
76
|
+
const recovered = await catchErrorAsync(async (error: any) =>
|
|
77
|
+
resultSuccess("should not be called"),
|
|
72
78
|
)(result);
|
|
73
79
|
expect(recovered.unwrapOrThrow()).toBe(42);
|
|
74
80
|
});
|
|
81
|
+
|
|
82
|
+
test("unwrapOrThrow", () => {
|
|
83
|
+
const result = resultSuccess(42);
|
|
84
|
+
const value = unwrapOrThrow(result);
|
|
85
|
+
expect(value).toBe(42);
|
|
86
|
+
});
|
|
75
87
|
});
|
|
76
88
|
|
|
77
89
|
describe("Result integration with ts-pipe", () => {
|
|
78
|
-
test("
|
|
79
|
-
var result = await
|
|
90
|
+
test("pipeAsync", async () => {
|
|
91
|
+
var result = await pipeAsync(
|
|
80
92
|
doSomething(),
|
|
81
93
|
andThenAsync(async (_e) => resultSuccess(new Date())),
|
|
82
94
|
andThen((r) => {
|
|
83
95
|
assertType<typeof r, Date>(true);
|
|
84
96
|
return resultSuccess("test");
|
|
85
|
-
})
|
|
97
|
+
}),
|
|
86
98
|
);
|
|
87
99
|
expect(result.unwrapOrThrow()).toBe("test");
|
|
88
100
|
});
|
|
@@ -94,7 +106,7 @@ describe("Result integration with ts-pipe", () => {
|
|
|
94
106
|
andThen((r) => {
|
|
95
107
|
assertType<typeof r, Date>(true);
|
|
96
108
|
return resultSuccess("test");
|
|
97
|
-
})
|
|
109
|
+
}),
|
|
98
110
|
);
|
|
99
111
|
expect(result.unwrapOrThrow()).toBe("test");
|
|
100
112
|
});
|
|
@@ -106,7 +118,7 @@ describe("Result integration with ts-pipe", () => {
|
|
|
106
118
|
andThen((r) => {
|
|
107
119
|
assertType<typeof r, Date>(true);
|
|
108
120
|
return resultSuccess("test");
|
|
109
|
-
})
|
|
121
|
+
}),
|
|
110
122
|
);
|
|
111
123
|
expect(result.unwrapOrThrow()).toBe("test");
|
|
112
124
|
});
|
package/src/result-functions.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ErrorType, Result, SuccessType } from "./result";
|
|
1
|
+
import { ErrorType, Result, SuccessType } from "./result.js";
|
|
2
2
|
|
|
3
3
|
export function andThen<TSuccess, TError, TResult extends Result<any, any>>(
|
|
4
|
-
callback: (value: TSuccess) => TResult
|
|
4
|
+
callback: (value: TSuccess) => TResult,
|
|
5
5
|
): (
|
|
6
|
-
result: Result<TSuccess, TError
|
|
6
|
+
result: Result<TSuccess, TError>,
|
|
7
7
|
) => Result<SuccessType<TResult>, TError | ErrorType<TResult>> {
|
|
8
8
|
return (result) => result.andThen(callback);
|
|
9
9
|
}
|
|
@@ -11,19 +11,19 @@ export function andThen<TSuccess, TError, TResult extends Result<any, any>>(
|
|
|
11
11
|
export function andThenAsync<
|
|
12
12
|
TSuccess,
|
|
13
13
|
TError,
|
|
14
|
-
TResult extends Result<any, any
|
|
14
|
+
TResult extends Result<any, any>,
|
|
15
15
|
>(
|
|
16
|
-
callback: (value: TSuccess) => Promise<TResult
|
|
16
|
+
callback: (value: TSuccess) => Promise<TResult>,
|
|
17
17
|
): (
|
|
18
|
-
result: Result<TSuccess, TError
|
|
18
|
+
result: Result<TSuccess, TError>,
|
|
19
19
|
) => Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>> {
|
|
20
20
|
return (result) => result.andThenAsync(callback);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function catchError<TSuccess, TError, TResult extends Result<any, any>>(
|
|
24
|
-
callback: (error: TError) => TResult
|
|
24
|
+
callback: (error: TError) => TResult,
|
|
25
25
|
): (
|
|
26
|
-
result: Result<TSuccess, TError
|
|
26
|
+
result: Result<TSuccess, TError>,
|
|
27
27
|
) => Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>> {
|
|
28
28
|
return (result) => result.catchError(callback);
|
|
29
29
|
}
|
|
@@ -31,11 +31,17 @@ export function catchError<TSuccess, TError, TResult extends Result<any, any>>(
|
|
|
31
31
|
export function catchErrorAsync<
|
|
32
32
|
TSuccess,
|
|
33
33
|
TError,
|
|
34
|
-
TResult extends Result<any, any
|
|
34
|
+
TResult extends Result<any, any>,
|
|
35
35
|
>(
|
|
36
|
-
callback: (error: TError) => Promise<TResult
|
|
36
|
+
callback: (error: TError) => Promise<TResult>,
|
|
37
37
|
): (
|
|
38
|
-
result: Result<TSuccess, TError
|
|
38
|
+
result: Result<TSuccess, TError>,
|
|
39
39
|
) => Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>> {
|
|
40
40
|
return (result) => result.catchErrorAsync(callback);
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
export function unwrapOrThrow<TSuccess>(
|
|
44
|
+
result: Result<TSuccess, never>,
|
|
45
|
+
): TSuccess {
|
|
46
|
+
return result.unwrapOrThrow();
|
|
47
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { resultSuccess } from "./result";
|
|
3
|
+
import { deserializeResult, serializeResult } from "./result-serialization";
|
|
4
|
+
|
|
5
|
+
describe("result-serialization", () => {
|
|
6
|
+
it("can be serialized and deserialized", () => {
|
|
7
|
+
const result = resultSuccess(42);
|
|
8
|
+
|
|
9
|
+
const serializedResult = serializeResult(result);
|
|
10
|
+
|
|
11
|
+
const stringifiedResult = JSON.stringify(serializedResult);
|
|
12
|
+
const parsedResult = JSON.parse(stringifiedResult);
|
|
13
|
+
expect(typeof parsedResult.andThen).toBe("undefined");
|
|
14
|
+
|
|
15
|
+
const deserializedResult = deserializeResult(parsedResult);
|
|
16
|
+
expect(typeof deserializedResult.andThen).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Result, resultError, resultSuccess, UnsafeResult } from "./result.js";
|
|
2
|
+
|
|
3
|
+
type SerializedResult = {
|
|
4
|
+
type: "ts-result";
|
|
5
|
+
isSuccess: boolean;
|
|
6
|
+
data: any;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function serializeResult<TSuccess, TError>(
|
|
10
|
+
value: Result<TSuccess, TError>,
|
|
11
|
+
): SerializedResult {
|
|
12
|
+
const unsafeResult = value as UnsafeResult<TSuccess, TError>;
|
|
13
|
+
if (unsafeResult.isSuccess()) {
|
|
14
|
+
return {
|
|
15
|
+
type: "ts-result",
|
|
16
|
+
isSuccess: true,
|
|
17
|
+
data: unsafeResult.getValueUnsafe(),
|
|
18
|
+
};
|
|
19
|
+
} else {
|
|
20
|
+
return {
|
|
21
|
+
type: "ts-result",
|
|
22
|
+
isSuccess: false,
|
|
23
|
+
data: unsafeResult.getErrorUnsafe(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isValueSerializedResult(value: unknown): value is SerializedResult {
|
|
29
|
+
return (
|
|
30
|
+
typeof value === "object" &&
|
|
31
|
+
value !== null &&
|
|
32
|
+
"type" in value &&
|
|
33
|
+
value.type === "ts-result"
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function deserializeResult(value: unknown) {
|
|
38
|
+
if (!isValueSerializedResult(value)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Could not deserialize value as ts-result: ${JSON.stringify(value)}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (value.isSuccess) {
|
|
45
|
+
return resultSuccess(value.data);
|
|
46
|
+
} else {
|
|
47
|
+
return resultError.fromError(value.data);
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/result.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
1
2
|
import {
|
|
2
3
|
resultSuccess,
|
|
3
4
|
resultError,
|
|
@@ -7,8 +8,9 @@ import {
|
|
|
7
8
|
resultSuccessVoid,
|
|
8
9
|
SuccessVoid,
|
|
9
10
|
ErrorUnknown,
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
UnsafeResult,
|
|
12
|
+
} from "./result.js";
|
|
13
|
+
import { assertType, expectToCompile } from "./utils/test/assert-type.js";
|
|
12
14
|
|
|
13
15
|
function createResult<TSuccess, TError>(): Result<TSuccess, TError> {
|
|
14
16
|
return resultSuccessVoid() as object as Result<TSuccess, TError>;
|
|
@@ -107,7 +109,30 @@ describe("Result Monad", () => {
|
|
|
107
109
|
}
|
|
108
110
|
return resultError.fromError(e);
|
|
109
111
|
});
|
|
110
|
-
type Expected = Result<
|
|
112
|
+
type Expected = Result<
|
|
113
|
+
number,
|
|
114
|
+
ErrorUnknown | ErrorWithCode<"error-code-2">
|
|
115
|
+
>;
|
|
111
116
|
assertType<typeof catchedResult, Expected>(true);
|
|
112
117
|
});
|
|
118
|
+
|
|
119
|
+
describe("UnsafeResult", () => {
|
|
120
|
+
test("returns value", () => {
|
|
121
|
+
const result = resultSuccess(42) as UnsafeResult<number, never>;
|
|
122
|
+
const value = result.getValueUnsafe();
|
|
123
|
+
expect(value).toBe(42);
|
|
124
|
+
});
|
|
125
|
+
test("returns error", () => {
|
|
126
|
+
const result = resultError.withCode("test" as const, {
|
|
127
|
+
value: 42,
|
|
128
|
+
}) as UnsafeResult<never, unknown>;
|
|
129
|
+
const value = result.getErrorUnsafe();
|
|
130
|
+
expect(value).toMatchObject({
|
|
131
|
+
code: "test",
|
|
132
|
+
data: {
|
|
133
|
+
value: 42,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
113
138
|
});
|
package/src/result.ts
CHANGED
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
export interface Result<
|
|
1
|
+
export interface Result<TSuccess, TError> {
|
|
2
|
+
isSuccess(): boolean;
|
|
2
3
|
andThen<TResult extends Result<any, any>>(
|
|
3
|
-
f: (value:
|
|
4
|
-
): Result<SuccessType<TResult>,
|
|
4
|
+
f: (value: TSuccess) => TResult,
|
|
5
|
+
): Result<SuccessType<TResult>, TError | ErrorType<TResult>>;
|
|
5
6
|
andThenAsync<TResult extends Result<any, any>>(
|
|
6
|
-
f: (value:
|
|
7
|
-
): Promise<Result<SuccessType<TResult>,
|
|
7
|
+
f: (value: TSuccess) => Promise<TResult>,
|
|
8
|
+
): Promise<Result<SuccessType<TResult>, TError | ErrorType<TResult>>>;
|
|
8
9
|
catchError<TResult extends Result<any, any>>(
|
|
9
|
-
f: (error:
|
|
10
|
-
): Result<
|
|
10
|
+
f: (error: TError) => TResult,
|
|
11
|
+
): Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>;
|
|
11
12
|
catchErrorAsync<TResult extends Result<any, any>>(
|
|
12
|
-
f: (error:
|
|
13
|
-
): Promise<Result<
|
|
14
|
-
unwrapOrThrow(errorCallback?: (e:
|
|
13
|
+
f: (error: TError) => Promise<TResult>,
|
|
14
|
+
): Promise<Result<TSuccess | SuccessType<TResult>, ErrorType<TResult>>>;
|
|
15
|
+
unwrapOrThrow(errorCallback?: (e: TError) => void): TSuccess;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface UnsafeResult<TSuccess, TError> extends Result<
|
|
19
|
+
TSuccess,
|
|
20
|
+
TError
|
|
21
|
+
> {
|
|
22
|
+
getValueUnsafe(): TSuccess;
|
|
23
|
+
getErrorUnsafe(): TError;
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
export function unwrapSuccessResult<T>(result: Result<T, never>): T {
|
|
18
27
|
if (result instanceof ResultSuccessImp) {
|
|
19
|
-
return result[
|
|
28
|
+
return result["value"];
|
|
20
29
|
}
|
|
21
|
-
throw new Error(
|
|
30
|
+
throw new Error("Unreachable code. Result is an error");
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
export type ErrorWithCode<TCode, TData = object> = { code: TCode; data: TData };
|
|
@@ -33,12 +42,12 @@ export function errorWithCode<TCode, TData>(
|
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
export type ErrorUnknown = {
|
|
36
|
-
code:
|
|
45
|
+
code: "unknown";
|
|
37
46
|
data: { message: string };
|
|
38
47
|
};
|
|
39
48
|
export function errorUnkown(message: string): ErrorUnknown {
|
|
40
49
|
return {
|
|
41
|
-
code:
|
|
50
|
+
code: "unknown",
|
|
42
51
|
data: { message },
|
|
43
52
|
};
|
|
44
53
|
}
|
|
@@ -72,16 +81,27 @@ export class resultError {
|
|
|
72
81
|
errorWithCode(code, data),
|
|
73
82
|
);
|
|
74
83
|
}
|
|
75
|
-
public static fromError<
|
|
76
|
-
TError1
|
|
77
|
-
|
|
84
|
+
public static fromError<TError1 extends ErrorWithCode<any, object>>(
|
|
85
|
+
error: TError1,
|
|
86
|
+
): Result<never, TError1> {
|
|
78
87
|
return new ResultErrorImp<TError1>(error);
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
class ResultSuccessImp<TSuccess1> implements
|
|
91
|
+
class ResultSuccessImp<TSuccess1> implements UnsafeResult<TSuccess1, never> {
|
|
83
92
|
constructor(private value: TSuccess1) {}
|
|
84
93
|
|
|
94
|
+
public getValueUnsafe(): TSuccess1 {
|
|
95
|
+
return this.value;
|
|
96
|
+
}
|
|
97
|
+
public getErrorUnsafe(): never {
|
|
98
|
+
throw new Error("This result is success, cannot get error");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public isSuccess() {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
85
105
|
public andThen<TSuccess2, TError2>(
|
|
86
106
|
f: (value: TSuccess1) => Result<TSuccess2, TError2>,
|
|
87
107
|
): Result<TSuccess2, TError2> {
|
|
@@ -111,9 +131,20 @@ class ResultSuccessImp<TSuccess1> implements Result<TSuccess1, never> {
|
|
|
111
131
|
}
|
|
112
132
|
}
|
|
113
133
|
|
|
114
|
-
class ResultErrorImp<TError1> implements
|
|
134
|
+
class ResultErrorImp<TError1> implements UnsafeResult<never, TError1> {
|
|
115
135
|
constructor(private error: TError1) {}
|
|
116
136
|
|
|
137
|
+
public getValueUnsafe(): never {
|
|
138
|
+
throw new Error("This result is error, cannot get value");
|
|
139
|
+
}
|
|
140
|
+
public getErrorUnsafe(): TError1 {
|
|
141
|
+
return this.error;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public isSuccess(): boolean {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
117
148
|
public andThen<TSuccess2, TError2>(
|
|
118
149
|
_f: (value: never) => Result<TSuccess2, TError2>,
|
|
119
150
|
): Result<TSuccess2, TError1 | TError2> {
|
|
@@ -155,4 +186,4 @@ export function makeSafePromise<T>(
|
|
|
155
186
|
return promise
|
|
156
187
|
.then((value) => resultSuccess(value))
|
|
157
188
|
.catch((error) => resultError.unknown(error.message));
|
|
158
|
-
}
|
|
189
|
+
}
|