What a set is
An array keeps every value you put in it, repeats included. Sometimes all you need to know is which values there are. A Set is built for that: it holds each value once, and adding a value that is already inside changes nothing.
let pets = new Set<string>(["cat", "dog", "cat"]);
pets.add("fish");
pets.add("dog");
console.log(pets.size);
console.log(pets.has("dog"));
The two console.log calls print 3 and true. The repeated "cat" went in once, "fish" was new, and the second "dog" was ignored.
The operations
new Set<string>()makes an empty set of strings. The part in angle brackets is the type of the values.s.add(x)putsxin the sets.s.has(x)istruewhenxis in the set andfalseotherwise.s.sizeis the number of values in the set. It is a property, so it has no parentheses.new Set(arr)builds a set from an array. Repeats go in once.
Checking s.has(x) is fast even for a big set, because the set does not look at the values one by one. An array's includes does exactly that.
Dropping repeats from an array
The most common use of a set is removing repeats. Build a set from the array, then spread the set back into an array with [...]:
const names = ["Ava", "Leo", "Ava", "Mia", "Leo"];
const unique = [...new Set(names)];
console.log(unique.join(" "), unique.length);
It prints Ava Leo Mia 3. Each name keeps its first position, and the array has 3 names, so a set and an array can be converted back and forth when you need the other one's tools.
Traps
- The names differ from arrays. A set counts with
size, notlength, and it checks withhas, notincludes. The compiler reportskids.lengthas an error, but the JavaScript it still writes runs, andkids.lengthquietly givesundefined. Callingkids.includes("Leo")stops the program withkids.includes is not a function. - No indexes. A set has no positions, so
s[0]does not give the first value. It givesundefined. Loop withfor...ofor copy the set into an array with[...s]. - Order. A TypeScript set remembers the order in which values were added. For
new Set([3, 1, 2, 3]),[...s]is3 1 2, and the second 3 does not move anything. - Types are not checked at run time. A
Set<number>that is asked about the string"1"answersfalse, because1and"1"are different values.
The exercise
A camp's sign-up array names has some names twice. The task is to build a set called kids from it, add Zoe and then Ava, and print Leo is coming if Leo is in the set. The code already prints the number of kids twice.
- Build the set:
let kids: Set<string> = new Set(names);. Ava and Leo appear twice in the array, so the set holds 3 names: Ava, Leo and Mia. - Add Zoe and Ava with one
addcall each. Zoe is new, so the size becomes 4. Ava is already there, so she changes nothing. - Test
kids.has("Leo")inside anifand print the message.
let names: string[] = ["Ava", "Leo", "Ava", "Mia", "Leo"];
let kids: Set<string> = new Set(names);
console.log(kids.size + " kids");
kids.add("Zoe");
kids.add("Ava");
console.log(kids.size + " kids");
if (kids.has("Leo")) {
console.log("Leo is coming");
}
The output is:
3 kids
4 kids
Leo is coming
Key takeaways
- A
Setholds each value once; adding a repeat does nothing. - Use
add,hasandsize, not the array namespush,includesandlength. new Set(array)is the quickest way to drop repeats from an array.- A set has no indexes, so
s[0]does not work.
