My first npm package is about sets
Tags: npm, firstpost, javascript, typescript
Published: 2021-02-16 16:35:42

Hi! This is my first DEV post. Recently I had to use some sets in my Javascript code that needed to contain objects as items. The problem is the browser `Set` object compares their items by equality. So I decide to create a micro-library in which you can  use sets that can handle all the set operation comaprinf the items with an id as a key.

Let me introduce you to the library [SmartSet](https://www.npmjs.com/package/smart-set)

# Installation

If you want to use my library you can install it easily by npm or yarn.
```shell
npm install smart-set

yarn add smart-set
```

# Creation and operations

The `SmartSet` class extends the `Set` class, so every member of `Set` is available, and compatible with the `Set` interface.

## Constructor
`SmartSet` has two template paramters: 
- `T` is the type of items
- `ID` is the type of the key (must be primitive)

`SmartSet` constructor requires a function that determines the id of an item which should be unique and primitive. The second parameter is a list of items of `T`, which will be the starting data of the set. These items will be unique in the set.
```typescript
import { SmartSet } from "smart-set";

interface Data { id: string };

const mySet = new SmartSet<Data, string>(item => item.id, [{ id: 'id1' }, { id: 'id2' }, { id: 'id1' }]);
```


## Addition
The `add(item: T)` and `addAll(items: T[])` functions add item(s) to the set uniquely by the given id function.
```typescript
mySet.add({ id: 'id3' });
mySet.add({ id: 'id1' });
mySet.addAll([{ id: 'id1' }, { id: 'id4' }, { id: 'id5' }]);
```

## Deletion
The `delete(item: T)` and `deleteId(id: ID)` functions delete an item by the given id function.
The `clear()` function deletes all elements.
```typescript
mySet.delete({ id: 'id3' });
mySet.deleteId('id1');
mySet.clear();
```

## Containment
The `has(item: T): boolean` and `hasId(id: ID): boolean` check whether an item is part of the set by the given id function.
```typescript
mySet.has({ id: 'id3' }) === false;
mySet.hasId('id1') === true;
```

## Iteration
`SmartSet` is iterable and has the `keys(): IterableIterator<ID>`, `values(): IterableIterator<T>` and `entries(): IterableIterator<[ID, T]>` functions for iterating the set. Keys are the values of the `ID` type.
```typescript
const mySet = new SmartSet<Data, string>(item => item.id, [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }]);

[...mySet.keys()] === ['id1', 'id2', 'id3'];

[...mySet.values()] === [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }];

[...mySet.entries()] === [['id1', { id: 'id1' }], ['id2', { id: 'id2' }], ['id3', { id: 'id3' }]];

[...mySet] === [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }];

mySet.forEach((value, key, set) => { /* something with the key, value and set */ })
```

## Set operations

`SmartSet` has some set operation that corresponds to the mathematics representation. These operations are immutable, so they return a new `SmartSet` instance and does not modify the original set. The methods accept regular `Set` objects, because it runs the ID creation function on the items.

`union(other: Set<T>): SmartSet<T, ID>`

`intersection(other: Set<T>): SmartSet<T, ID>`

`difference(other: Set<T>): SmartSet<T, ID>`

`symmetricDifference(other: Set<T>): SmartSet<T, ID>`

```typescript
let result;
const setA = new SmartSet<Data, string>(item => item.s, [ { s: '1' }, { s: '2' } ]);
const setB = new SmartSet<Data, string>(item => item.s, [ { s: '1' }, { s: '3' } ]);

result = setA.union(setB); //  [ { s: '1' }, { s: '2' }, { s: '3' } ]
result = setA.intersection(setB); //  [ { s: '1' } ]
result = setA.difference(setB); //  [ { s: '2' } ]
result = setB.difference(setA); //  [ { s: '3' } ]
result = setA.symmetricDifference(setB); //  [ { s: '2' }, { s: '3' } ]
```

# Closing words

As I am new to library publishing and open source world it would be a huge help if you could take a look at my source code or report an issue at the repository of the package at [github](https://github.com/dbalazs97/smart-set). Thanks for reading my first post.