diff --git a/.npmignore b/.npmignore
index f0daeba..60750e8 100644
--- a/.npmignore
+++ b/.npmignore
@@ -14,4 +14,5 @@ npm-debug.log
.github
/test
-/badges
\ No newline at end of file
+/badges
+/coverage
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b76d989..fe9d5d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 1.2.0 (October 6, 2021)
+
+### Release 1.2.0
+
+- defining Result interface: IResult
+- new feature: **_Error Set_** -> `createErrorSet`, `ErrSet`
+
+---
+
## 1.1.3 (October 5, 2021)
### Release 1.1.3
diff --git a/LICENSE b/LICENSE
index 360273e..2aeddb0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2021 just-do-halee(=Hwakyeom Kim)
+Copyright 2021 just-do-halee(=Hwakyeom Kim)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index d6e8568..07175cd 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,17 @@
# `rusultTs`
-Rust **_Result Implementation for Typescript_**, simply. i.e. Modern error handling library. (no dependencies, pure Typescript code about 50 lines) 100% [[coverage]](https://github.com/just-do-halee/rusultts/actions/workflows/main.yml)
+Rust **_Result Implementation for Typescript_**, simply. i.e. Modern error handling library. (no dependencies, pure Typescript code about 50 lines) 100% [[coverage]][ci-url]
-![Coverage lines](./badges/badge-lines.svg)
-![Coverage functions](./badges/badge-functions.svg)
-![Coverage branches](./badges/badge-branches.svg)
-![Coverage statements](./badges/badge-statements.svg)
+[![Coverage lines](./badges/badge-lines.svg)][ci-url]
+[![Coverage functions](./badges/badge-functions.svg)][ci-url]
+[![Coverage branches](./badges/badge-branches.svg)][ci-url]
+[![Coverage statements](./badges/badge-statements.svg)][ci-url]
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
-[![CI](https://github.com/just-do-halee/rusultts/actions/workflows/main.yml/badge.svg)](https://github.com/just-do-halee/rusultts/actions/workflows/main.yml)
+[![CI](https://github.com/just-do-halee/rusultts/actions/workflows/main.yml/badge.svg)][ci-url]
[![License][license-image]][license-url]
[[changelog]](CHANGELOG.md)
@@ -79,6 +79,43 @@ try {
}
```
+## **Advanced**
+
+```ts
+import { createErrorSet } from 'rusultts';
+
+const err = createErrorSet({
+ notFound: 'not found',
+ somethingWrong: 'something wrong...',
+ wrongHeader: 'please fix your header.',
+ undefinedValue: 'this value is undefined:',
+ dividedByZero: 'do not divide by Zero.',
+ dividedByNegative: 'well, you did divide as Negative value.',
+});
+```
+
+```ts
+import { ResultBox, Ok, Err } from 'rusultts';
+// and also import our **const `err`**
+
+function divide(a: number, b: number): ResultBox => {
+ if (b === 0) {
+ return err.new('dividedByZero', b); // autocompleted string
+ } else if (b < 0) {
+ return err.new('dividedByNegative', b);
+ }
+ return Ok.new(a / b);
+};
+
+try {
+ divide(4, -2).unwrap();
+} catch (e) {
+ const val1 = err.match(e, 'dividedByZero').unwrap(); // val1 === undefined
+ const val2 = err.match(e, 'dividedByNegative').unwrap(); // val2 === '-2'
+ const val3 = err.match({ is: 'not errorType' }, 'dividedByNegative').unwrap(); // throw new Error()
+}
+```
+
## **License**
[MIT](LICENSE)
@@ -89,3 +126,4 @@ try {
[downloads-url]: https://npmcharts.com/compare/rusultts?minimal=true
[license-url]: https://opensource.org/licenses/MIT
[license-image]: https://img.shields.io/npm/l/rusultts
+[ci-url]: https://github.com/just-do-halee/rusultts/actions/workflows/main.yml
diff --git a/dist/rusultts.d.ts b/dist/rusultts.d.ts
index f44cbe6..699c19d 100644
--- a/dist/rusultts.d.ts
+++ b/dist/rusultts.d.ts
@@ -1,7 +1,18 @@
+/**
+ * kind of internal subject(ok or err)
+ */
export declare type ResultObject = {
readonly error?: Error;
readonly value: T;
};
+/**
+ * international interface
+ */
+export interface IResult {
+ readonly isOk: boolean;
+ readonly isErr: boolean;
+ unwrap(): T | never;
+}
/**
* ## Examples
*```ts
@@ -25,7 +36,7 @@ export declare type ResultObject = {
* }
*```
*/
-export declare abstract class ResultBox {
+export declare abstract class ResultBox implements IResult {
protected readonly val: ResultObject;
readonly isOk: boolean;
readonly isErr: boolean;
@@ -96,3 +107,75 @@ export declare class Err extends ResultBox {
* easy one, has value of Error as `null`
*/
export declare type Result = ResultBox;
+/**
+ * error's message pair object
+ * ## Example
+ * ```ts
+ * const mp: MessagePair = {
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * }
+ * ```
+ */
+export declare type MessagePair = {
+ [key: string]: string;
+};
+export declare type TOrUndefinedToNull = T extends undefined ? null : T;
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+export declare class ErrSet {
+ readonly messagePair: M;
+ constructor(messagePair: M);
+ /**
+ * creates and return the error that have already been set.
+ */
+ new(errorMessageType: keyof M, val: TOrUndefinedToNull): Err>;
+ /**
+ *
+ * @param {Error} e the error in the scope of try~catch.
+ * @param {MessagePair} errorMessageType in the MessagePair.
+ * @returns if `e` is not Error type, return Err<, Type>, or returns Ok which means `e` === the error of errorMessageType then returns `error value` or `undefined`.
+ *
+ * ## Example
+ *```ts
+ * const test = divide(4, 0);
+ * try {
+ * test.unwrap();
+ * } catch (e) {
+ * const val = err.match(e, 'dividedByZero').unwrap();
+ * if(val) {
+ * return val;
+ * } else {
+ * return 'unexpected error.';
+ * }
+ * }
+ * ```
+ */
+ match(e: Error | unknown, errorMessageType: keyof M): ResultBox;
+}
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+export declare const createErrorSet: (messagePair: M) => ErrSet;
diff --git a/dist/rusultts.js b/dist/rusultts.js
index 5a71905..fa1141e 100644
--- a/dist/rusultts.js
+++ b/dist/rusultts.js
@@ -1,5 +1,5 @@
"use strict";
-// rusultTs
+// (c) 2021 just-do-halee(=Hwakyeom Kim)
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
@@ -16,7 +16,7 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
-exports.Err = exports.Ok = exports.ResultBox = void 0;
+exports.createErrorSet = exports.ErrSet = exports.Err = exports.Ok = exports.ResultBox = void 0;
/**
* ## Examples
*```ts
@@ -141,3 +141,74 @@ var Err = /** @class */ (function (_super) {
return Err;
}(ResultBox));
exports.Err = Err;
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+var ErrSet = /** @class */ (function () {
+ function ErrSet(messagePair) {
+ this.messagePair = messagePair;
+ }
+ /**
+ * creates and return the error that have already been set.
+ */
+ ErrSet.prototype.new = function (errorMessageType, val) {
+ return Err.new(this.messagePair[errorMessageType], val);
+ };
+ /**
+ *
+ * @param {Error} e the error in the scope of try~catch.
+ * @param {MessagePair} errorMessageType in the MessagePair.
+ * @returns if `e` is not Error type, return Err<, Type>, or returns Ok which means `e` === the error of errorMessageType then returns `error value` or `undefined`.
+ *
+ * ## Example
+ *```ts
+ * const test = divide(4, 0);
+ * try {
+ * test.unwrap();
+ * } catch (e) {
+ * const val = err.match(e, 'dividedByZero').unwrap();
+ * if(val) {
+ * return val;
+ * } else {
+ * return 'unexpected error.';
+ * }
+ * }
+ * ```
+ */
+ ErrSet.prototype.match = function (e, errorMessageType) {
+ if (!(e instanceof Error)) {
+ return Err.new("e is unknown type:", e);
+ }
+ var _a = Err.eSplit(e), message = _a[0], value = _a[1];
+ return Ok.new(message === this.messagePair[errorMessageType] ? value : undefined);
+ };
+ return ErrSet;
+}());
+exports.ErrSet = ErrSet;
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+var createErrorSet = function (messagePair) {
+ return new ErrSet(messagePair);
+};
+exports.createErrorSet = createErrorSet;
diff --git a/package.json b/package.json
index 2118b8d..b5e433f 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "rusultts",
"main": "dist/rusultts.js",
"types": "dist/rusultts.d.ts",
- "version": "1.1.3",
+ "version": "1.2.0",
"description": "Rust Result Implementation for Typescript, simply. i.e. Modern error handling library.",
"author": "just-do-halee ",
"license": "MIT",
diff --git a/src/rusultts.ts b/src/rusultts.ts
index d3b304f..db8ea85 100644
--- a/src/rusultts.ts
+++ b/src/rusultts.ts
@@ -1,10 +1,23 @@
-// rusultTs
+// (c) 2021 just-do-halee(=Hwakyeom Kim)
+/**
+ * kind of internal subject(ok or err)
+ */
export type ResultObject = {
readonly error?: Error;
readonly value: T;
};
+/**
+ * international interface
+ */
+export interface IResult {
+ readonly isOk: boolean;
+ readonly isErr: boolean;
+ // Returning internal value or Throw an error
+ unwrap(): T | never;
+}
+
/**
* ## Examples
*```ts
@@ -28,7 +41,7 @@ export type ResultObject = {
* }
*```
*/
-export abstract class ResultBox {
+export abstract class ResultBox implements IResult {
readonly isOk: boolean;
readonly isErr: boolean;
protected constructor(protected readonly val: ResultObject) {
@@ -128,3 +141,96 @@ export class Err extends ResultBox {
* easy one, has value of Error as `null`
*/
export type Result = ResultBox;
+
+/**
+ * error's message pair object
+ * ## Example
+ * ```ts
+ * const mp: MessagePair = {
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * }
+ * ```
+ */
+export type MessagePair = { [key: string]: string };
+
+export type TOrUndefinedToNull = T extends undefined ? null : T;
+
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+export class ErrSet {
+ constructor(public readonly messagePair: M) {}
+ /**
+ * creates and return the error that have already been set.
+ */
+ new(
+ errorMessageType: keyof M,
+ val: TOrUndefinedToNull
+ ): Err> {
+ return Err.new(this.messagePair[errorMessageType], val);
+ }
+ /**
+ *
+ * @param {Error} e the error in the scope of try~catch.
+ * @param {MessagePair} errorMessageType in the MessagePair.
+ * @returns if `e` is not Error type, return Err<, Type>, or returns Ok which means `e` === the error of errorMessageType then returns `error value` or `undefined`.
+ *
+ * ## Example
+ *```ts
+ * const test = divide(4, 0);
+ * try {
+ * test.unwrap();
+ * } catch (e) {
+ * const val = err.match(e, 'dividedByZero').unwrap();
+ * if(val) {
+ * return val;
+ * } else {
+ * return 'unexpected error.';
+ * }
+ * }
+ * ```
+ */
+ match(
+ e: Error | unknown,
+ errorMessageType: keyof M
+ ): ResultBox {
+ if (!(e instanceof Error)) {
+ return Err.new(`e is unknown type:`, e);
+ }
+ const [message, value] = Err.eSplit(e);
+ return Ok.new(
+ message === this.messagePair[errorMessageType] ? value : undefined
+ );
+ }
+}
+
+/**
+ * creates errors that have already been set.
+ * ## Example
+ * ```ts
+ * const err = createErrorSet({
+ * notFound: 'not found',
+ * somethingWrong: 'something wrong...',
+ * wrongHeader: 'please fix your header.'
+ * });
+ *
+ * err.new('wrongHeader'); // === Err.new('please fix your header.', null)
+ * ```
+ */
+export const createErrorSet = (
+ messagePair: M
+): ErrSet => {
+ return new ErrSet(messagePair);
+};
diff --git a/test/rusultts.test.ts b/test/rusultts.test.ts
index 188445b..d8ce403 100644
--- a/test/rusultts.test.ts
+++ b/test/rusultts.test.ts
@@ -1,4 +1,11 @@
-import { Result, ResultBox, Ok, Err } from '../src/rusultts';
+import {
+ Result,
+ ResultBox,
+ Ok,
+ Err,
+ createErrorSet,
+ ErrSet,
+} from '../src/rusultts';
import { Stack } from './test.types';
describe('make some results', () => {
@@ -56,23 +63,38 @@ describe('make some results', () => {
});
let divide: (a: number, b: number) => ResultBox;
+ let err: ErrSet<{
+ dividedByZero: 'do not divide by Zero.';
+ dividedByNegative: 'well, you did divide as Negative value.';
+ }>;
beforeEach(() => {
+ err = createErrorSet({
+ dividedByZero: 'do not divide by Zero.',
+ dividedByNegative: 'well, you did divide as Negative value.',
+ });
+ expect(err.messagePair.dividedByZero).toEqual('do not divide by Zero.');
+ expect(err.messagePair.dividedByNegative).toEqual(
+ 'well, you did divide as Negative value.'
+ );
+
divide = (a: number, b: number): ResultBox => {
if (b === 0) {
- return Err.new(`b cannot be 0.`, b);
+ return err.new('dividedByZero', b);
+ } else if (b < 0) {
+ return err.new('dividedByNegative', b);
}
return Ok.new(a / b);
};
});
- it('divide-> 4 / 2', () => {
+ it('divides-> 4 / 2', () => {
const test = divide(4, 2);
expect(test.isOk).toEqual(true);
expect(test.isErr).toEqual(false);
expect(test.unwrap()).toEqual(2);
});
- it('divide-> 4 / 0', () => {
+ it('divides-> 4 / 0', () => {
const test = divide(4, 0);
expect(test.isOk).toEqual(false);
expect(test.isErr).toEqual(true);
@@ -87,6 +109,19 @@ describe('make some results', () => {
}
});
+ it('divides-> 4 / -2', () => {
+ const test = divide(4, -2);
+ try {
+ test.unwrap();
+ } catch (e) {
+ expect(() =>
+ err.match({ type: 'unknown' }, 'dividedByNegative').unwrap()
+ ).toThrowError('e is unknown type::--> [object Object]');
+ expect(err.match(e, 'dividedByNegative').unwrap()).toEqual('-2');
+ expect(err.match(e, 'dividedByZero').unwrap()).toBeUndefined();
+ }
+ });
+
it('should be ok after entire testing', () => {
// just for fun
let stack = Stack.withCapacity(-10);