Collections

discord.js comes with a utility class known as Collection. It extends JavaScript's native Map class, so it has all the Map features and more!

If you're not familiar with Map, read MDN's page on it before continuing. You should be familiar with Array methods as well. We will also use some ES6 features, so read up here if you do not know what they are.

Warning

A Map allows for an association between unique keys and their values. For example, how can you transform every value or filter the entries in a Map easily? This is the point of the Collection class!

Array-like Methods

Many of the methods on Collection correspond to their namesake in Array. One of them is find:


_10
// Assume we have an array of users and a collection of the same users.
_10
array.find((u) => u.discriminator === '1000');
_10
collection.find((u) => u.discriminator === '1000');

The interface of the callback function is very similar between the two. For arrays, callbacks usually pass the parameters (value, index, array), where value is the value iterated to, index is the current index, and array is the array. For collections, you would have (value, key, collection). Here, value is the same, but key is the key of the value, and collection is the collection itself instead.

Methods that follow this philosophy of staying close to the Array interface are as follows:

  • find
  • filter - Note that this returns a Collection rather than an Array.
  • map - Yet this returns an Array of values instead of a Collection!
  • every
  • some
  • reduce
  • concat
  • sort

Converting to Array

Since Collection extends Map, it is an iterable, and can be converted to an Array through either Array.from() or spread syntax (...collection).


_11
// For values.
_11
Array.from(collection.values());
_11
[...collection.values()];
_11
_11
// For keys.
_11
Array.from(collection.keys());
_11
[...collection.keys()];
_11
_11
// For [key, value] pairs.
_11
Array.from(collection);
_11
[...collection];

Many people convert Collections to Arrays way too much! This can lead to unnecessary and confusing code. Before you use Array.from() or similar, ask yourself if whatever you are trying to do can't be done with the given Map or Collection methods or with a for-of loop.

Warning

Extra Utilities

Some methods are not from Array and are instead entirely new to standard JavaScript.


_16
// A random value.
_16
collection.random();
_16
_16
// The first value.
_16
collection.first();
_16
_16
// The first 5 values.
_16
collection.first(5);
_16
_16
// Similar to `first`, but from the end.
_16
collection.last();
_16
collection.last(2);
_16
_16
// Removes anything that meets the condition from the collection.
_16
// Sort of like `filter`, but in-place.
_16
collection.sweep((user) => user.username === 'Bob');

A more complicated method is partition, which splits a single Collection into two new Collections based on the provided function. You can think of it as two _filter_ methods, but done at the same time:


_10
// `bots` is a Collection of users where their `bot` property was true.
_10
// `humans` is a Collection where the property was false instead!
_10
const [bots, humans] = collection.partition((u) => u.bot);
_10
_10
// Both return true.
_10
bots.every((b) => b.bot);
_10
humans.every((h) => !h.bot);