rsult 1.0.1 → 1.1.0
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/deno.json +5 -0
- package/package.json +17 -17
- package/readme.md +1 -1
- package/src/lib.ts +2 -2
- package/src/option.ts +11 -8
- package/src/result.test.ts +1 -15
- package/src/result.ts +46 -31
- package/tsconfig.json +6 -1
package/deno.json
ADDED
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
"name": "rsult",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src/lib.ts",
|
|
6
|
+
"repository": "https://github.com/indicium-ag/rsult",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "Kenan Sulayman <kenan@sly.mn>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@swc/core": "^1.4.12",
|
|
15
|
+
"@swc/jest": "^0.2.36",
|
|
16
|
+
"@types/jest": "^29.5.12",
|
|
17
|
+
"jest": "^29.7.0"
|
|
18
|
+
}
|
|
19
19
|
}
|
package/readme.md
CHANGED
|
@@ -276,6 +276,7 @@ console.log(result); // "Parsed content: {"parsed":"Resource content"}"
|
|
|
276
276
|
#### Conversion Methods
|
|
277
277
|
- `into_ok()`: Converts from `IResultCore<T, E>` to `T`.
|
|
278
278
|
- `into_err()`: Converts from `IResultCore<T, E>` to `E`.
|
|
279
|
+
- `transmute()`: Changes the type of `Result<T, E>` to `Result<T, never>` or `Result<never, E>`, respectively. This is particularly useful when trying to forward a `ResultErr` returned by a function whose error type overlaps with the returned error type of the current function, but whose value type does not.
|
|
279
280
|
|
|
280
281
|
#### Checking and Transforming Methods
|
|
281
282
|
- `is_ok_and(f: (value: T) => boolean)`: Checks if the result is Ok and the contained value passes a specified condition.
|
|
@@ -301,7 +302,6 @@ console.log(result); // "Parsed content: {"parsed":"Resource content"}"
|
|
|
301
302
|
|
|
302
303
|
#### Iteration and Flattening Methods
|
|
303
304
|
- `iter()`: Returns an iterator over the potentially contained value.
|
|
304
|
-
- `transpose()`: Attempts to transpose a `Result` of a `Promise` into a `Promise` of a `Result`.
|
|
305
305
|
- `flatten()`: Flattens a nested `Result` if the contained value is itself a `Result`.
|
|
306
306
|
|
|
307
307
|
## Contributing
|
package/src/lib.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './result';
|
|
2
|
-
export * from './option';
|
|
1
|
+
export * from './result.ts';
|
|
2
|
+
export * from './option.ts';
|
package/src/option.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type Option<T> =
|
|
1
|
+
export type Option<T> =
|
|
2
|
+
OptionSome<T> | OptionNone<T>;
|
|
2
3
|
|
|
3
4
|
export interface IOptionCheck<T> {
|
|
4
5
|
/**
|
|
@@ -178,7 +179,7 @@ export interface IOptionUtility<T> {
|
|
|
178
179
|
* const myOption is None<number>();
|
|
179
180
|
* const value = myOption.unwrap_or_default(); // 0
|
|
180
181
|
*/
|
|
181
|
-
unwrap_or_default(): T;
|
|
182
|
+
unwrap_or_default(): T | null;
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
export interface IOptionMutate<T> {
|
|
@@ -280,7 +281,8 @@ export interface IOption<T> extends
|
|
|
280
281
|
|
|
281
282
|
export class OptionSome<T> implements IOption<T> {
|
|
282
283
|
readonly _tag = 'Some' as const;
|
|
283
|
-
|
|
284
|
+
// @ts-ignore
|
|
285
|
+
readonly _T: T;
|
|
284
286
|
|
|
285
287
|
constructor(readonly value: T) { }
|
|
286
288
|
|
|
@@ -352,7 +354,7 @@ export class OptionSome<T> implements IOption<T> {
|
|
|
352
354
|
return this.value;
|
|
353
355
|
}
|
|
354
356
|
|
|
355
|
-
unwrap_or_default(): T {
|
|
357
|
+
unwrap_or_default(): T | null {
|
|
356
358
|
return this.value;
|
|
357
359
|
}
|
|
358
360
|
|
|
@@ -408,7 +410,8 @@ export class OptionSome<T> implements IOption<T> {
|
|
|
408
410
|
|
|
409
411
|
export class OptionNone<T> implements IOption<T> {
|
|
410
412
|
private readonly _tag: 'None' = 'None';
|
|
411
|
-
|
|
413
|
+
// @ts-ignore
|
|
414
|
+
private readonly _T: T;
|
|
412
415
|
|
|
413
416
|
is_some(): this is never {
|
|
414
417
|
return false;
|
|
@@ -470,7 +473,7 @@ export class OptionNone<T> implements IOption<T> {
|
|
|
470
473
|
return fn();
|
|
471
474
|
}
|
|
472
475
|
|
|
473
|
-
unwrap_or_default() {
|
|
476
|
+
unwrap_or_default(): T | null {
|
|
474
477
|
return null as any;
|
|
475
478
|
}
|
|
476
479
|
|
|
@@ -499,11 +502,11 @@ export class OptionNone<T> implements IOption<T> {
|
|
|
499
502
|
}
|
|
500
503
|
}
|
|
501
504
|
|
|
502
|
-
export const Some = <T>(val: T) => {
|
|
505
|
+
export const Some = <T>(val: T): Option<T> => {
|
|
503
506
|
return new OptionSome<T>(val);
|
|
504
507
|
};
|
|
505
508
|
|
|
506
|
-
export const None = <T>() => {
|
|
509
|
+
export const None = <T>(): Option<T> => {
|
|
507
510
|
return new OptionNone<T>();
|
|
508
511
|
};
|
|
509
512
|
|
package/src/result.test.ts
CHANGED
|
@@ -341,20 +341,6 @@ describe('Result', () => {
|
|
|
341
341
|
});
|
|
342
342
|
});
|
|
343
343
|
|
|
344
|
-
describe('transpose', () => {
|
|
345
|
-
it('returns ResultOk<number, _> for Result<number, _>', () => {
|
|
346
|
-
const resultPromise = Ok(5);
|
|
347
|
-
const transposed = resultPromise.transpose();
|
|
348
|
-
expect(transposed).toEqual(Ok(5));
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
it('returns ResultErr<_, Error> for Result<_, Error>', () => {
|
|
352
|
-
const resultPromise = Err(new Error("Error"));
|
|
353
|
-
const transposed = resultPromise.transpose();
|
|
354
|
-
expect(transposed).toEqual(Err(new Error("Error")));
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
|
|
358
344
|
describe('flatten', () => {
|
|
359
345
|
it('flattens nested Ok Result', () => {
|
|
360
346
|
const nestedOk = Ok(Ok(5));
|
|
@@ -452,7 +438,7 @@ describe('Result', () => {
|
|
|
452
438
|
const promise = Promise.reject(new Error(errorMsg));
|
|
453
439
|
const result = await result_from_promise(promise);
|
|
454
440
|
expect(result.is_err()).toBe(true);
|
|
455
|
-
expect(
|
|
441
|
+
expect(result.unwrap_err().message).toBe(errorMsg);
|
|
456
442
|
});
|
|
457
443
|
});
|
|
458
444
|
});
|
package/src/result.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Option, None, Some } from './option';
|
|
1
|
+
import { Option, None, Some } from './option.ts';
|
|
2
2
|
|
|
3
|
-
export type Result<T, E> =
|
|
3
|
+
export type Result<T, E> =
|
|
4
|
+
ResultOk<T, E> | ResultErr<T, E>;
|
|
4
5
|
|
|
5
6
|
export interface IResultCore<T, E> {
|
|
6
7
|
/**
|
|
@@ -120,6 +121,30 @@ export interface IResultCore<T, E> {
|
|
|
120
121
|
* console.log(result.into_err());
|
|
121
122
|
*/
|
|
122
123
|
into_err(): E;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Converts between different forms of `Result`, allowing the error type to be widened.
|
|
127
|
+
*
|
|
128
|
+
* If called on a `ResultOk<T, E>`, it will return a `Result<T, never>`, effectively discarding
|
|
129
|
+
* the error type. This is useful when you want to use the `Result` in a context that expects
|
|
130
|
+
* a `Result` with a specific error type, but you know that the `Result` is an `Ok` variant.
|
|
131
|
+
*
|
|
132
|
+
* If called on a `ResultErr<T, E>`, it will return a `Result<never, E>`, effectively discarding
|
|
133
|
+
* the value type. This is useful when you want to use the `Result` in a context that expects
|
|
134
|
+
* a `Result` with a specific value type, but you know that the `Result` is an `Err` variant.
|
|
135
|
+
*
|
|
136
|
+
* This is particularly useful when trying to forward a ResultErr returned by a function whose
|
|
137
|
+
* error type overlaps with the returned error type of the current function, but whose value type
|
|
138
|
+
* does not.
|
|
139
|
+
*
|
|
140
|
+
* Usage Example:
|
|
141
|
+
* const result: Result<number, Error> = Ok<number, Error>(5);
|
|
142
|
+
* const transmuted: Result<number, never> = result.transmute();
|
|
143
|
+
*
|
|
144
|
+
* const result: Result<number, Error> = Err<number, Error>(new Error("Failure"));
|
|
145
|
+
* const transmuted: Result<never, Error> = result.transmute();
|
|
146
|
+
*/
|
|
147
|
+
transmute(): Result<T, never> | Result<never, E>;
|
|
123
148
|
}
|
|
124
149
|
|
|
125
150
|
export interface IResultExt<T, E> extends IResultCore<T, E> {
|
|
@@ -323,19 +348,6 @@ export interface IResultIteration<T, E> extends IResultCore<T, E> {
|
|
|
323
348
|
*/
|
|
324
349
|
iter(): IterableIterator<T>;
|
|
325
350
|
|
|
326
|
-
/**
|
|
327
|
-
* Attempts to transpose a `Result` of a `Promise` into a `Promise` of a `Result`.
|
|
328
|
-
* @returns A Promise of a Result if the inner value is a Promise, null otherwise.
|
|
329
|
-
*
|
|
330
|
-
* Usage Example:
|
|
331
|
-
* async function example() {
|
|
332
|
-
* const resultPromise = Ok(Promise.resolve(5));
|
|
333
|
-
* const transposed = resultPromise.transpose(); // Result<Promise<5>, E> -> Promise<Result<5, E>> | null
|
|
334
|
-
* console.log(await transposed); // Prints Ok(5) if the promise resolves successfully.
|
|
335
|
-
* }
|
|
336
|
-
*/
|
|
337
|
-
transpose(): Result<T, E>;
|
|
338
|
-
|
|
339
351
|
/**
|
|
340
352
|
* Flattens a nested `Result` if the contained value is itself a `Result`.
|
|
341
353
|
* @returns A single-layer `Result`, by stripping one layer of `Result` container.
|
|
@@ -365,8 +377,10 @@ export const isResultErr = <T, E>(val: any): val is ResultErr<T, E> => {
|
|
|
365
377
|
|
|
366
378
|
export class ResultOk<T, E> implements IResult<T, E> {
|
|
367
379
|
private readonly _tag = 'Ok' as const;
|
|
368
|
-
|
|
369
|
-
private readonly
|
|
380
|
+
// @ts-ignore
|
|
381
|
+
private readonly _T: T;
|
|
382
|
+
// @ts-ignore
|
|
383
|
+
private readonly _E: E;
|
|
370
384
|
|
|
371
385
|
constructor(readonly value: T) {
|
|
372
386
|
}
|
|
@@ -469,10 +483,6 @@ export class ResultOk<T, E> implements IResult<T, E> {
|
|
|
469
483
|
return this.value;
|
|
470
484
|
}
|
|
471
485
|
|
|
472
|
-
transpose(): Result<T, E> {
|
|
473
|
-
return new ResultOk<T, E>(this.value);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
486
|
flatten(): Result<UnwrapResult<T>, E> {
|
|
477
487
|
if (this.value instanceof ResultOk || this.value instanceof ResultErr) {
|
|
478
488
|
return this.value;
|
|
@@ -490,12 +500,18 @@ export class ResultOk<T, E> implements IResult<T, E> {
|
|
|
490
500
|
into_err(): never {
|
|
491
501
|
throw new Error('Called Result.into_err() on an Ok value: ' + this.value);
|
|
492
502
|
}
|
|
503
|
+
|
|
504
|
+
transmute(): Result<T, never> {
|
|
505
|
+
return this as any;
|
|
506
|
+
}
|
|
493
507
|
}
|
|
494
508
|
|
|
495
509
|
export class ResultErr<T, E> implements IResult<T, E> {
|
|
496
510
|
private readonly _tag: 'Err' = 'Err';
|
|
497
|
-
|
|
498
|
-
private readonly
|
|
511
|
+
// @ts-ignore
|
|
512
|
+
private readonly _T: T;
|
|
513
|
+
// @ts-ignore
|
|
514
|
+
private readonly _E: E;
|
|
499
515
|
|
|
500
516
|
constructor(readonly value: E) {
|
|
501
517
|
}
|
|
@@ -597,12 +613,8 @@ export class ResultErr<T, E> implements IResult<T, E> {
|
|
|
597
613
|
return fn(this.value);
|
|
598
614
|
}
|
|
599
615
|
|
|
600
|
-
transpose(): Result<T, E> {
|
|
601
|
-
return new ResultErr<T, E>(this.value);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
616
|
flatten(): Result<UnwrapResult<T>, E> {
|
|
605
|
-
return this.
|
|
617
|
+
return new ResultErr(this.value) as Result<never, E>;
|
|
606
618
|
}
|
|
607
619
|
|
|
608
620
|
into_ok(): T {
|
|
@@ -612,13 +624,16 @@ export class ResultErr<T, E> implements IResult<T, E> {
|
|
|
612
624
|
into_err(): E {
|
|
613
625
|
return this.value;
|
|
614
626
|
}
|
|
615
|
-
}
|
|
616
627
|
|
|
617
|
-
|
|
628
|
+
transmute(): Result<never, E> {
|
|
629
|
+
return this as any;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
export const Ok = <T, E>(val: T): Result<T, never> => {
|
|
618
633
|
return new ResultOk<T, E>(val) as Result<T, never>;
|
|
619
634
|
};
|
|
620
635
|
|
|
621
|
-
export const Err = <T, E>(val: E) => {
|
|
636
|
+
export const Err = <T, E>(val: E): Result<never, E> => {
|
|
622
637
|
return new ResultErr<T, E>(val) as Result<never, E>;
|
|
623
638
|
};
|
|
624
639
|
|
package/tsconfig.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"module": "commonjs",
|
|
4
4
|
"target": "es2020",
|
|
5
|
+
"outDir": "./dist",
|
|
5
6
|
"lib": [
|
|
6
7
|
"es6",
|
|
7
8
|
"es7",
|
|
@@ -10,6 +11,8 @@
|
|
|
10
11
|
"allowJs": false,
|
|
11
12
|
"moduleResolution": "node",
|
|
12
13
|
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"emitDeclarationOnly": true,
|
|
13
16
|
"noImplicitReturns": true,
|
|
14
17
|
"noImplicitThis": true,
|
|
15
18
|
"noImplicitAny": true,
|
|
@@ -29,6 +32,8 @@
|
|
|
29
32
|
"src/*.ts"
|
|
30
33
|
],
|
|
31
34
|
"exclude": [
|
|
32
|
-
"node_modules/"
|
|
35
|
+
"node_modules/",
|
|
36
|
+
"src/**/*.test.ts",
|
|
37
|
+
"src/*.test.ts"
|
|
33
38
|
]
|
|
34
39
|
}
|