Skip to content

Commit

Permalink
fix: The library doesn't throw exceptions whn non Either values are…
Browse files Browse the repository at this point in the history
… used.

BREAKING CHANGE: Until now the library had some logic to throw exceptions when a non `Either` value was used. This is not the case anymore.
Now, when a non `Either` value is detected from the `isLeft` or `isRight` functions (which are also used internally) a `Left` is returned.
  • Loading branch information
joanllenas committed Dec 8, 2019
1 parent b889a71 commit 52c4aea
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 41 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ npm install ts.data.either --save
## Example

```ts
import { map, Either, left, right, caseOf} from 'ts.data.either';
import { map, Either, left, right, caseOf } from 'ts.data.either';

type Band = {
artist: string;
Expand Down Expand Up @@ -122,10 +122,12 @@ isRight(left(new Error('Wrong!'))); // false

`isLeft<T>(value: Either<T>): boolean`

Returns true if a value is an instance of `Left`.
Returns true if a value is not an instance of `Right`.

```ts
isLeft(right(5)); // false
isLeft(left('Hi!')); // true
isLeft(null); // true
```

### withDefault
Expand Down
53 changes: 23 additions & 30 deletions src/either.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import * as chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
const expect = chai.expect;

const createError = <T>(value: T) => `Value "${value}" is not an Either type`;
const anError = () => new Error('Something is wrong');
const add1 = (n: number) => n + 1;
const removeFirstElement = <T>(arr: T[]): T[] => {
Expand All @@ -34,13 +33,13 @@ describe('Either', () => {
it('should return true when Right is provided', () => {
expect(isRight(right('hola'))).to.be.true;
});
it('should throw when a non Either type is provided', () => {
it('should return false when a non Either type is provided', () => {
const nonEither: any = [1, 2, 3];
expect(() => isRight(nonEither)).to.throw(createError(nonEither));
expect(isRight(nonEither)).to.be.false;
});
it('should throw when null or undefined is provided', () => {
expect(() => isRight(null)).to.throw(createError(null));
expect(() => isRight(undefined)).to.throw(createError(undefined));
it('should return false when null or undefined is provided', () => {
expect(isRight(null)).to.be.false;
expect(isRight(undefined)).to.be.false;
});
});

Expand All @@ -51,13 +50,13 @@ describe('Either', () => {
it('should return true when Left is provided', () => {
expect(isLeft(left(anError()))).to.be.true;
});
it('should throw when a non Either type is provided', () => {
it('should return true when a non Either type is provided', () => {
const nonEither: any = [1, 2, 3];
expect(() => isLeft(nonEither)).to.throw(createError(nonEither));
expect(isLeft(nonEither)).to.be.true;
});
it('should throw when null or undefined is provided', () => {
expect(() => isLeft(null)).to.throw(createError(null));
expect(() => isLeft(undefined)).to.throw(createError(undefined));
it('should return true when null or undefined is provided', () => {
expect(isLeft(null)).to.be.true;
expect(isLeft(undefined)).to.be.true;
});
});

Expand All @@ -68,13 +67,13 @@ describe('Either', () => {
it('should return the default value when Left is provided', () => {
expect(withDefault(left(anError()), 0)).to.equal(0);
});
it('should throw when a non Either type is provided', () => {
it('should return the default value when a non Either type is provided', () => {
const nonEither: any = [1, 2, 3];
expect(() => withDefault(nonEither, 2)).to.throw(createError(nonEither));
expect(withDefault(nonEither, 2)).to.eq(2);
});
it('should throw when null or undefined is provided', () => {
expect(() => withDefault(null, 1)).to.throw(createError(null));
expect(() => withDefault(undefined, 1)).to.throw(createError(undefined));
it('should return the default value when null or undefined is provided', () => {
expect(withDefault(null, 1)).to.eq(1);
expect(withDefault(undefined, 1)).to.eq(1);
});
});

Expand Down Expand Up @@ -103,12 +102,10 @@ describe('Either', () => {
const list = map(removeFirstElement, right([]));
expect(isLeft(list)).to.be.true;
});
it('should throw when mapping over null, undefined or any non Either type', () => {
expect(() => map(add1, null)).to.throw(createError(null));
expect(() => map(add1, undefined)).to.throw(createError(undefined));
expect(() => map(add1, {} as any)).to.throw(
createError('[object Object]')
);
it('should return a Left when mapping over null, undefined or any non Either type', () => {
expect(isLeft(map(add1, null))).to.be.true;
expect(isLeft(map(add1, undefined))).to.be.true;
expect(isLeft(map(add1, {} as any))).to.be.true;
});
});

Expand All @@ -134,14 +131,10 @@ describe('Either', () => {
);
expect(withDefault(result, ['default val'])).to.eql(['default val']);
});
it('should throw when chaining over null, undefined or any non Either type', () => {
expect(() => andThen(a => right(a), null)).to.throw(createError(null));
expect(() => andThen(a => right(a), undefined)).to.throw(
createError(undefined)
);
expect(() => andThen(a => right(a), {} as any)).to.throw(
createError('[object Object]')
);
it('should return left throw when chaining over null, undefined or any non Either type', () => {
expect(isLeft(andThen(a => right(a), null))).to.be.true;
expect(isLeft(andThen(a => right(a), undefined))).to.be.true;
expect(isLeft(andThen(a => right(a), {} as any))).to.be.true;
});
});

Expand Down
10 changes: 1 addition & 9 deletions src/either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ class Left<T> {

export type Either<T> = Right<T> | Left<T>;

const assertIsEither = function<T>(value: Either<T>) {
if (!(value instanceof Right || value instanceof Left)) {
throw new Error(`Value "${value}" is not an Either type`);
}
};

export const right = <T>(value: T): Either<T> => {
return new Right(value);
};
Expand All @@ -24,13 +18,11 @@ export const left = <T>(error: Error): Either<T> => {
};

export const isRight = <T>(value: Either<T>): boolean => {
assertIsEither(value);
return value instanceof Right;
};

export const isLeft = <T>(value: Either<T>): boolean => {
assertIsEither(value);
return value instanceof Left;
return !(value instanceof Right);
};

export const withDefault = <T>(value: Either<T>, defaultValue: T): T => {
Expand Down

0 comments on commit 52c4aea

Please sign in to comment.