TypeScript Set

In TypeScript, the Set is a new data structure introduced in ES6, similar to Map that allows us to store distinct values. It is similar to an array or a List but with the distinction that it doesn’t allow duplicate values.

1. Creating Set

To create a Set in TypeScript, we can simply use the Set constructor:

const directions = new Set<string>();

To create a Set with initial values we can pass the values in an array.

const directions = new Set<string>(['east', 'west']);

2. Add, Retrieve and Delete Values from Set

  1. set.add(v) – adds the specified value to the Set.
  2. set.has(v) – checks the existence of the specified value in the Set.
  3. set.delete(v) – deletes the specified value from the Set.
  4. set.clear() – clears all the values from the Set.
  5. set.size – ‘size‘ property will return the size of Set.
//Create a Set
let diceEntries = new Set<number>();
 
//Add values
diceEntries.add(1);
diceEntries.add(2);
diceEntries.add(3);
diceEntries.add(4).add(5).add(6);   //Chaining of add() method is allowed
 
//Check value is present or not
diceEntries.has(1);                 //true
diceEntries.has(10);                //false
 
//Size of Set 
diceEntries.size;                   //6
 
//Delete a value from set
diceEntries.delete(6);              // true
 
//Clear whole Set
diceEntries.clear();                //Clear all entries

3. Iterating over a Set

We can iterate over a Set using the for-of and forEach loops.

let mySet = new Set<number>();
 
//Added 6 entries into the set
mySet.add(1).add(2).add(3).add(4).add(5).add(6);
 
//Iterate over set entries
for (let currentNumber of mySet) {
    console.log(currentNumber);     //Prints 1 2 3 4 5 6
}
 
// Iterate set entries with forEach
mySet.forEach(function(value) {
  console.log(value);               //Prints 1 2 3 4 5 6
});

mySet.forEach(value => console.log(value));     //Prints 1 2 3 4 5 6

4. Set of Custom Types – Object Equality

By default, Sets in TypeScript use SameValueZero algorithm to determine if two objects are the same. This equality works great for simple types (string, boolean and number) but does not work with custom types.

Consider the following example where we have a Set of numbers. We added the number ‘2’ twice, but it was added only once in the Set.

const numSet = new Set<number>();

numSet.add(1).add(2).add(2);

// '2' is added only once
console.log(numSet);  //{1, 2}

But, if we try to add complex types in a Set, we do not get the expected results because of how the equality is checked, by default, in ES 6.

type Person = Record<string, string>;

const personSet = new Set<Person>();

const john: Person = {
  name: "John"
};
const johnDuplicate: Person = {
  name: "John"
};

personSet.add(john);
personSet.add(johnDuplicate);

console.log(personSet); // Two objects are present with same content

If we want to use custom types or objects and store them in a Set, considered equal based on their content, we must manage the comparison for equality, ourselves.

Because the default equality in ES6 uses the object references, we must create a custom data structure that handles the desired object equality rules as follows:

class SetWithContentEquality<T> {
    private items: T[] = [];
    private getKey: (item: T) => string;

    constructor(getKey: (item: T) => string) {
        this.getKey = getKey;
    }

    add(item: T): void {
        const key = this.getKey(item);
        if (!this.items.some(existing => this.getKey(existing) === key)) {
            this.items.push(item);
        }
    }

    has(item: T): boolean {
        return this.items.some(existing => this.getKey(existing) === this.getKey(item));
    }

    values(): T[] {
        return [...this.items];
    }
}

Now, when we store the Person objects in the Set, the two objects will be considered equal if they have the same name. It is the expected behavior in most cases.

//Compatre Person objects by their 'name' attribute
const personSet = new SetWithContentEquality<Person>(person => person.name);  

const john: Person = {
    name: "John"
};
const johnDuplicate: Person = {
    name: "John"
};

personSet.add(john);
personSet.add(johnDuplicate);

console.log(personSet.values()); // One object with content "John"

Drop me your questions in the comments section.

Happy Learning !!

Comments

Subscribe
Notify of
guest
5 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode