New RxJS Primitives release, new operators + Typescript 4
Tags: typescript, rxjs, angular, showdev
Published: 2020-11-18 11:33:29

---
title: New RxJS Primitives release, new operators + Typescript 4
published: true
description: New release of the RxJS Primitives Library
tags: typescript,rxjs,angular,showdev
canonical_url: https://tane.dev/2020/11/new-rxjs-primitives-release-new-operators-typescript-4/
---

This week I released new versions of my [RxJS](https://github.com/ReactiveX/rxjs) libraries in [rxjs-primitives](https://github.com/tanepiper/rxjs-primitives). 
Since it's released I've added a few new utility operators. Some of these have been out for a while since I originally wrote about the release, so I've highlighted them here as they may be useful to some developers.

You can check out the [full docs here](https://tanepiper.github.io/rxjs-primitives).

### Typescript 4

Upgrading to Typescript 4 has allowed the removal of [polymorphic functions](http://tane.dev/2020/05/polymorphic-typescript-function-overloading-with-rest-parameters/) in place of
[Vardic Tuple Types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) and is why there is a major bump on all packages.

This can be seen in the [old](https://github.com/tanepiper/rxjs-primitives/blob/0f7d8f5c9bb5c6b9e6d1bc149ba661a464c52018/libs/rxjs/string/src/lib/concat.ts) and [new](https://github.com/tanepiper/rxjs-primitives/blob/master/libs/rxjs/string/src/lib/concat.ts) 
`concat` operator in the `rxjs-string` package.

Most of the tests have also been converted to [rxjs-marbles](https://www.npmjs.com/package/rxjs-marbles) allowing for more robust
Observable testing (if you are working with RxJS I highly recommend checking it out, it integrates well with runners like Jest).

```ts
it(
    'should return string value of string ending with passed character',
    marbles((m) => {
      const input = m.hot('-a-b-c-|', { a: 'test', b: 'testing', c: 'gone' });
      const subs = '^------!';
      const expected = m.cold('---y---|', { y: 'testing' });
      m.expect(input.pipe(filterEndsWith('g'))).toBeObservable(expected);
      m.expect(input).toHaveSubscriptions(subs);
    }),
  );
```

### rxjs-array

> npm install @tinynodes/rxjs-array

In the [array module](https://tanepiper.github.io/rxjs-primitives/modules/array.html) there are some operators to use with finding 
the difference or intersection between a source and a passed array, for example:

```ts
of(['a', 'b', 'd'])
 .pipe(difference(['a', 'c']))
 .subscribe(console.log) // ['b', 'd']

of(['a', 'b', 'd'])
 .pipe(intersects(['a', 'c']))
 .subscribe(console.log) // ['a']
```

These methods accept an array, or an `Observable<Array>` of items to compare against.

The module also included a [binarySearch](https://tanepiper.github.io/rxjs-primitives/modules/array.html#binarysearch) operator which returns
a custom [BinarySearchResult](https://tanepiper.github.io/rxjs-primitives/modules/array.html#binarysearchresult) tuple.

### rxjs-boolean

> npm install @tinynodes/rxjs-boolean

A new [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) operator `luhnCheck` is provided that does validation on
numbers such as credit cards, ID cards and other value schemes that use the check.

```ts
fromString('4485275742308327')
    .pipe(luhnCheck())
    .subscribe(console.log) // true, this is a valid credit card
```

### rxjs-number

> npm install @tinynodes/rxjs-number

`inRange` / `outOfRange` and `filterInRange` / `filterOutOfRange` both all two numbers, the filter methods return the value from the source observable within the range of those values,
while the other methods return a boolean value if in range. An optional third value will include/exclude the range value
based on the method

```ts
fromNumber([-1, 0, 1, 2, 10, 11])
 .pipe(filterInRange(0, 10))
 .subscribe(console.log) // [0, 1, 2, 10]

// Passing true as the third parameter, the range numbers will also be excluded
fromNumber([-1, 0, 1, 2, 10, 11])
 .pipe(filterInRange(0, 10, true))
 .subscribe(console.log) // [1, 2]
```

### rxjs-string

> npm install @tinynodes/rxjs-string

New operators such as [titleize](https://tanepiper.github.io/rxjs-primitives/modules/string.html#titleize), [repeat](https://tanepiper.github.io/rxjs-primitives/modules/string.html#repeat) and 
[match](https://tanepiper.github.io/rxjs-primitives/modules/string.html#match) add new utility features for strings. Where they can they also support localisation:

```ts
fromString('Mary had a little lamb')
 .pipe(titleize())
 .subscribe(console.log) // 'Mary Had A Little Lamb'

fromString('Mary had ä little lamb')
 .pipe(titleize('de-DE'))
 .subscribe(console.log) // 'Mary Had Ä Little Lamb'
```

### rxjs-utility

> npm install @tinynodes/rxjs-utility

The [utility module](https://tanepiper.github.io/rxjs-primitives/modules/utility.html) contains some specialised tap operators such as `tapIf`, `startWithTap` and `tapOnSubscribe`.
These provide a way to do side effects.  With `startWithTap` it can be used with Angular to do a form touch, also `tapOnSubscribe` will
fire when there is a subscription to the Observable:

```ts
// Only touch on first value change
form.valueChange.pipe(
 startWithTap(() => this.onTouch())
).subscribe()

// Fire when a component subscribes to the service bus
this.serviceBus.pipe(
  tapOnSubscribe((name: string) => console.log(`New Subscription to ${name}`))
).subscribe()
```

The `tapIf` will only fire if a passed method result is truthy:

```ts
fromNumber([1, 2, 3, 4, 5, 6]).pipe(
  tapIf((val) => val % 2 === 0), (val) => console.log(val)
).subscribe() // 2, 4, 6
```

The last operator is `mapIfSource` which might be a bit of a weird one but I hope might become useful.

The operator takes the value from the source and passes to a predicate method, and depending on the result will `map` the
result of a passed method. A simple example would be:

```ts
fromNumber([1, 2, 3, 4, 5, 6]).pipe(
  mapIfSource(
    (value) => val % 2 === 0,
    (value) => val * 10,
    (value) => val * 20
  )
).subscribe() // 20, 20, 60 40, 100, 60
```

Here, if the result of the predicate is true multiply by 10, otherwise by 20. The method is typed to allow different return values
based on the result (so you will have to handle the type later). For example we could even turn it into a
FizzBuzz operator:

```ts
export function fizzbuzz(): OperatorFunction<number, string | number> {
  return (source: Observable<number>) =>
    source.pipe(
      mapIfSource<number, string, number>(
        (value) => value % 15 == 0 || value % 3 == 0 || value % 5 == 0,
        (value) => (value % 15 == 0 ? `FizzBuzz` : value % 3 === 0 ? 'Fizz' : 'Buzz'),
        (value) => value
     )
  );
}

// And now we use it in our code
fromNumber([1, 3, 5, 15, 16]).pipe(
  fizzbuzz(),
).subscribe() // 1, 'Fizz', 'Buzz', 'FizzBuzz', 16
```

Hopefully you'll find these operators useful and feel free to leave feedback and suggestions.