scats
v1.4.2
Published
Useful scala classes in typescript
Downloads
511
Maintainers
Readme
scats
Useful scala classes in typescript
Install
npm i scats
Monads
Collection
Represents the collection of items of some type.
import {Collection, Nil} from "scats";
const empty = Collection.empty; // empty collection
const empty2 = Nil; // empty collection
const example = new Collection([1, 2, 3]); // create instance from array
const example2 = Collection.fill(3)(idx => idx + 1); // Collection.of(1, 2, 3)
const c = Collection.of(1, 2, 3);
for (let el of c) {
console.log(el); // 1, 2, 3
}
c.slice(2, 5); // Collection.of(3)
c.map(e => e + 1); // Collection.of(2, 3, 4)
Collection.of(1, 2).flatMap(x => Collection.of(x, x + 1)); // Collection.of(1, 2, 2, 3)
Collection.of(1, Collection.of(2, 3), 4).flatten<number>(); // Collection.of(1, 2, 3, 4)
Collection.of(1, 2, 3).get(1); // 2
Collection.of(1, 2, 3).toArray; // [1, 2, 3]
Collection.of(1, 2, 3).reverse; // Collection.of(3, 2, 1)
Collection.of(2, 3, 1).sort((a, b) => a - b); // Collection.of(1, 2, 3)
Collection.of({x: 2}, {x: 1}, {x: 3}).sortBy(el => el.x); // Collection.of(1, 2, 3)
Collection.of(1, 2).appended(3); // Collection.of(1, 2, 3)
Collection.of(1, 2).appendedAll(Collection.of(3, 4)); // Collection.of(1, 2, 3, 4)
Collection.of(1, 2).prepended(0); // Collection.of(0, 1, 2)
Collection.of(1, 2).prependedAll(Collection.of(-1, 0)); // Collection.of(-1, 0, 1, 2)
Collection.of(1, 2).concat(Collection.of(3, 4)); // Collection.of(1, 2, 3, 4)
Collection.of(1, 2, 2).toSet; // HashSet.of(1, 2)
Collection.of(1, 2, 2).distinct; // Collection.of(1, 2)
Collection.of({x: 2}, {x: 1}, {x: 2}).distinctBy(el => el.x); // Collection.of({x: 2}, {x: 1})
Collection.of({id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}).toMap(el => [el.id, el.name]); // HashMap(1 -> 'Alice', 2 -> 'Bob')
c.sum(identity); // 6. We have to provide identity to convert element to number
c.take(2); // Collection.of(1, 2)
c.drop(1); // Collection.of(2, 3);
c.head; // 1
Option
Represents a possibly empty value.
import {option} from "scats";
const a = null;
const b = option(a); // b = none;
const c = 1;
const d = option(c); // d = some(1);
Try
Represents the result of error prone block.
import {Try} from 'scats';
const okResult = Try(() => 1); // a = success(1);
const failedResult = Try(() => { throw new Error(2) }); // b = failure(new Error(2));
okResult.toOption; // some(1)
failedResult.toOption; // none
okResult.toEither; // right(1)
failedResult.toEither; // left(new Error(2))
okResult.toEitherMapLeft(error => 3); // right(1)
failedResult.toEitherMapLeft(error => 3); // left(3)
okResult.map(value => value + 1); // success(2);
failedResult.map(value => value + 1); // failure(new Error(2));
okResult.isSuccess; // true
okResult.isFailure; // false
failedResult.isSuccess; // false
failedResult.isFailure; // true
okResult.match({
success: value => 100,
failure: error => 200
}); // 100
failedResult.match({
success: value => 100,
failure: error => 200
}); // 200
okResult.foreach(value => console.log(value)); // prints 1
failedResult.foreach(value => console.log(value)); // prints nothing
okResult.tapFailure(error => console.log(error.message)); // prints nothing
failedResult.tapFailure(error => console.log(error.message)); // prints 2
okResult.recover(error => 2); // success(1)
failedResult.recover(error => 2); // success(2)
failedResult.recover(error => { throw new Error('fallback'); }); // failure(new Error('fallback'));
okResult.recoverWith(error => success(2)); // success(1)
failedResult.recoverWith(error => success(2)); // success(2)
failedResult.recoverWith(error => failure(new Error('fallback'))); // failure(new Error('fallback'));
Also works with promises:
import {Try} from 'scats';
const a = await Try.promise(() => Promise.resolve(1)); // a = success(1);
await a.mapPromise(x => Promise.resolve(x)); // success(1)
Either
Represents the value, marked as left or right. Either is right-biased.
import {left, right, forComprehension} from 'scats';
const r = right('123'); // Right('123');
const l = left('left value'); // Left('123');
right(123).isRight; // true
right(123).isLeft; // false
left('left value').isRight; // false
left('left value').isLeft; // true
right(123).match({
right: () => 'right',
left: () => 'left'
}); // 'right'
left('left value').match({
right: () => 'right',
left: () => 'left'
}); // 'left'
right(123).fold(
leftValue => console.log(`left: ${leftValue}`),
rightValue => console.log(`right: ${rightValue}`)
); // 'right: 123'
left('left value').fold(
leftValue => console.log(`left: ${leftValue}`),
rightValue => console.log(`right: ${rightValue}`)
); // 'left: left value'
right(123).swap; // left(123);
right(123).foreach(x => console.log(x)); // 123
left(123).foreach(x => console.log(x)); // prints nothing
right(123).getOrElse(() => 1); // 123
right(123).getOrElseValue(1); // 123
left(123).getOrElse(() => 1); // 1
left(123).getOrElseValue(1); // 1
right(123).orElse(() => right(444)); // right(123)
right(123).orElseValue(right(444)); // right(123)
left(123).orElse(() => right(444)); // right(444)
left(123).orElseValue(right(444)); // right(444)
right(123).contains(123); // true
right(123).contains(124); // false
left(123).contains(123); // false
left(123).contains(124); // false
right(123).forall(x => x >= 10); // true
right(123).forall(x => x < 10); // false
left(123).forall(x => x >= 10); // false
left(123).forall(x => x < 10); // fales
right(123).exists(x => x >= 10); // true
right(123).exists(x => x < 10); // false
left(123).exists(x => x >= 10); // false
left(123).exists(x => x < 10); // fales
right(123).map(x => x + 1); // right(124)
right(123).left.map(x => x + 1); // right(123)
left(123).map(x => x + 1); // right(123)
left(123).left.map(x => x + 1); // right(124)
right(123).toCollection; // Collection.of(123)
left(123).toCollection; // Collection.empty
right(123).toOption; // Some(123)
left(123).toOption; // None
right(123).toTry; // Success(123)
left(123).toTry; // Failure(new Error(123))
right(123).left; // left-biased Either
forComprehension(
step('s', () => left('flower').left),
step('m', () => left('bird').left),
).yield(({s, m}) => s.length + m.length); // left(10)
HashMap
import {HashMap} from 'scats';
const map = HashMap.of(['1', 1], ['2', 3]);
map.toMap; // Map('1' -> 1, '2' -> 2)
map.toArray; // [['1', 1], ['2', 2]]
map.size; // 1
map.isEmpty; // false
HashMap.empty.isEmpty; // true
map.nonEmpty; // true
map.get('1'); // some(1)
map.get('5'); // none
map.getOrElse('1', () => 5); // 1
map.getOrElse('5', () => 5); // 5
map.keySet; // HashSet.of('1', '2')
map.keys; // Collection.of('1', '2')
map.values; // Collection.of(1, 2)
map.entries; // Collection.of(['1', 1], ['2', 2])
map.appendedAll(HashMap.of(['3', 3])); // HashMap.of(['1', 1], ['2', 2], ['3', 3])
map.set('2', 3); // HashMap.of(['1', 1], ['2', 3])
map.removed('2'); // HashMap.of(['1', 1])
map.updated('2', 4); // HashMap.of(['1', 1], ['2', 4])
HashSet
import {HashSet} from 'scats';
const set1 = HashSet.of(1, 2);
const set2 = HashSet.of(2, 3);
set1.size; // 2
set1.isEmpty; // false
set1.nonEmpty; // true
set1.filter(x => x > 1); // HashSet.of(2)
set1.filterNot(x => x > 1); // HashSet.of(1)
set1.map(x => x + 1); // HashSet.of(2, 3)
set1.toCollection; // Collection.of(2, 3) - order may be different
set1.toMap(x => [x, x]); // HashMap.of([1, 1], [2, 2])
set1.contains(1); // true
set1.appended(2); // HashSet.of(1, 2)
set1.appendedAll(HashSet.of(1, 2)); // HashSet.of(1, 2)
set1.removed(1); // HashSet.empty
set1.removedAll(HashSet.of(1, 2)); // HashSet.empty
set1.intersect(set2); // HashSet.of(2)
set1.union(set2); // HashSet.of(1, 2, 3)
forComprehension
import {forComprehension, step} from 'scats';
function toNum(x: string) {
return Try(() => {
const res = parseInt(x);
if (isNaN(res)) {
throw new Error(`${x} is not a number`);
} else {
return res;
}
});
}
forComprehension(
step('num1', () => toNum('1')),
step('num2', () => toNum('2')),
step('num3', () => toNum('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // success(6)
forComprehension(
step('num1', () => toNum('1')),
step('num2', () => toNum('s2')),
step('num3', () => toNum('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // failure(new Error('s2 is not a number')
// with collections:
forComprehension(
step('i', () => Collection.of(1, 2)),
step('j', () => Collection.of(4, 3))
).yield(({i, j}) => [i, j]); // Collection.of([1, 4], [1, 3], [2, 4], [2, 3])
forComprehension(
step('i', () => Collection.of(1, 2)),
step('j', () => Collection.of(2, 1)).if(({i, j}) => i + j === 3)
).yield(({i, j}) => [i, j]); // Collection.of([1, 2], [2, 1])
// with promises
function toNumPromise(x: string): Promise<TryLike<number>> {
return Promise.resolve(Try(() => {
const res = parseInt(x);
if (isNaN(res)) {
throw new Error(`${x} is not a number`);
} else {
return res;
}
}));
}
await forComprehension.promise(
task('num1', () => toNumPromise('1')),
task('num2', () => toNumPromise('2')),
task('num3', () => toNumPromise('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // success(6)
await forComprehension.promise(
task('num1', () => toNumPromise('1')),
task('num2', () => toNumPromise('s2')),
task('num3', () => toNumPromise('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // failure(new Error('s2 is not a number')
await forComprehension.promise(
task('num1', () => toNumPromise('1')),
task('num2', () => toNumPromise('2')).if(({num2}) => num2 > 10),
task('num3', () => toNumPromise('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // failure(new Error("Predicate does not hold for '2'")
await forComprehension.promise(
task('num1', () => toNumPromise('1')),
task('num2', () => { throw new Error('Error in task'); }),
task('num3', () => toNumPromise('3')),
).yield(({num1, num2, num3}) => num1 + num2 + num3); // throws Error('Error in task')
ArrayBuffer
Represents the mutable collection of items of some type backed by array.
import {mutable} from "scats";
import ArrayBuffer = mutable.ArrayBuffer;
const empty = ArrayBuffer.empty; // []
const example = new ArrayBuffer([1, 2, 3]); // create instance from array
const example2 = ArrayBuffer.fill(3)(idx => idx + 1); // ArrayBuffer.of(1, 2, 3)
const c = ArrayBuffer.of(1, 2, 3);
for (let el of c) {
console.log(el); // 1, 2, 3
}
c.slice(2, 5); // ArrayBuffer.of(3)
c.map(e => e + 1); // ArrayBuffer.of(2, 3, 4) (new instance)
ArrayBuffer.of(1, 2).flatMap(x => ArrayBuffer.of(x, x + 1)); // ArrayBuffer.of(1, 2, 2, 3)
ArrayBuffer.of(1, ArrayBuffer.of(2, 3), 4).flatten<number>(); // ArrayBuffer.of(1, 2, 3, 4)
ArrayBuffer.of(1, 2, 3).get(1); // 2
ArrayBuffer.of(1, 2, 3).toArray; // [1, 2, 3]
ArrayBuffer.of(1, 2, 3).reverse; // ArrayBuffer.of(3, 2, 1)
ArrayBuffer.of(2, 3, 1).sort((a, b) => a - b); // ArrayBuffer.of(1, 2, 3)
ArrayBuffer.of({x: 2}, {x: 1}, {x: 3}).sortBy(el => el.x); // ArrayBuffer.of(1, 2, 3)
ArrayBuffer.of(1, 2).append(3); // ArrayBuffer.of(1, 2, 3) - same instance
ArrayBuffer.of(1, 2).appended(3); // ArrayBuffer.of(1, 2, 3) - new instance
ArrayBuffer.of(1, 2).appendAll(ArrayBuffer.of(3, 4)); // ArrayBuffer.of(1, 2, 3, 4) - same instance
ArrayBuffer.of(1, 2).appendAll([3, 4]); // ArrayBuffer.of(1, 2, 3, 4) - same instance
ArrayBuffer.of(1, 2).appendedAll(ArrayBuffer.of(3, 4)); // ArrayBuffer.of(1, 2, 3, 4) - new instance
ArrayBuffer.of(1, 2).prepend(0); // ArrayBuffer.of(0, 1, 2) - same instance
ArrayBuffer.of(1, 2).prepended(0); // ArrayBuffer.of(0, 1, 2) - new instance
ArrayBuffer.of(1, 2).prepended(ArrayBuffer.of(-1, 0)); // ArrayBuffer.of(-1, 0, 1, 2) - same instance
ArrayBuffer.of(1, 2).prependedAll(ArrayBuffer.of(-1, 0)); // ArrayBuffer.of(-1, 0, 1, 2) - new instance
ArrayBuffer.of(1, 2).concat(ArrayBuffer.of(3, 4)); // ArrayBuffer.of(1, 2, 3, 4)
ArrayBuffer.of(1, 2, 2).toSet; // HashSet.of(1, 2)
ArrayBuffer.of(1, 2, 2).distinct; // ArrayBuffer.of(1, 2) - new instance
ArrayBuffer.of({x: 2}, {x: 1}, {x: 2}).distinctBy(el => el.x); // ArrayBuffer.of({x: 2}, {x: 1}) - new instance
ArrayBuffer.of({id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}).toMap(el => [el.id, el.name]); // HashMap(1 -> 'Alice', 2 -> 'Bob')
c.sum(identity); // 6. We have to provide identity to convert element to number
c.take(2); // Collection.of(1, 2)
c.drop(1); // Collection.of(2, 3);
c.head; // 1
mutable.HashMap
import {mutable} from "scats";
const map = new mutable.HashMap<string, number>()
map.set('Alice', 11); // ('Alice' -> 11)
map.set('Bob', 12); // ('Alice' -> 11, 'Bob' -> 12)
map.clear(); // ()
map.put('Steve', 14); // returns some(14), map: ('Steve' -> 14)
map.update('Alice', 11); // ('Steve' -> 14, 'Alice' -> 11)
map.remove('Alice'); // ('Steve' -> 14)
map.addOne(['Bob', 12]); // ('Steve' -> 14, 'Bob' -> 12)
map.subtractOne('Bob'); // ('Steve' -> 14)
map.addAll([['Alice', 11], ['Bob', 12]]); // ('Steve' -> 14, 'Alice' -> 11, 'Bob' -> 12)
map.mapValuesInPlace(([name, age]) => age + 1); // ('Steve' -> 15, 'Alice' -> 12, 'Bob' -> 13)
map.filterInPlace(([name, age]) => age > 13); // ('Steve' -> 15)
mutable.HashSet
import {mutable} from "scats";
const set = new mutable.HashSet<string, number>()
set.add(1); // true. set = [1]
set.add(1); // false. set = [1]
set.clear(); // []]
set.add(1); // true. set = [1]
set.remove(2); // false. set = [1]
set.remove(1); // true. set = []
set.addAll([2, 3]); // set = [1, 2, 3]
set.filterInPlace(x => x > 2); // [3]