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 ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@int/rsult",
3
+ "version": "1.1.0",
4
+ "exports": "./src/lib.ts"
5
+ }
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
- "name": "rsult",
3
- "version": "1.0.1",
4
- "description": "",
5
- "main": "src/lib.ts",
6
- "repository": "https://github.com/indicium-ag/rsult",
7
- "keywords": [],
8
- "author": "",
9
- "license": "ISC",
10
- "devDependencies": {
11
- "@swc/core": "^1.4.12",
12
- "@swc/jest": "^0.2.36",
13
- "@types/jest": "^29.5.12",
14
- "jest": "^29.7.0"
15
- },
16
- "scripts": {
17
- "test": "echo \"Error: no test specified\" && exit 1"
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> = OptionSome<T> | OptionNone<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
- readonly _T!: T;
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
- private readonly _T!: T;
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
 
@@ -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((await result.unwrap_err()).message).toBe(errorMsg);
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> = ResultOk<T, E> | ResultErr<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
- private readonly _T!: T;
369
- private readonly _E!: E;
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
- private readonly _T!: T;
498
- private readonly _E!: E;
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.transpose() as Result<never, E>;
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
- export const Ok = <T, E>(val: T) => {
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
  }