Set.prototype.intersection()
Returns a new collection holding only the values present in both this one and another set-like object.
intersection(other)- Added in JavaScript ES2025
Parameters
| Parameter | Type | Description |
|---|---|---|
$other | Set | set-like object | A Set, or any set-like object: one exposing a numeric size property, a has() method taking an element and returning a boolean, and a keys() method returning an iterator of the elements. |
Return value
SetA new Set containing the elements present in both this set and other, ordered as they appear in whichever of the two is smaller.
Errors
Throws a TypeError if other is not set-like (a plain array is not), or if called on a value that is not a real Set instance.
Changelog
- PHP ES2025Added along with union(), difference() and the other set-relation methods; Baseline newly available since June 2024, so older engines need a polyfill.
intersection() is A ∩ B: a new collection of the values both sides hold. Neither operand is modified, and the result is a real Set even when other was only set-like.
The implementation is deliberately asymmetric for speed. If this collection has more elements than other.size, the engine iterates other and tests membership here; otherwise it iterates this one and calls other.has(). Cost therefore tracks the smaller collection, which is why intersecting a two-element filter against a hundred-thousand-element collection is cheap.
The ordering surprise
That optimisation leaks into the result: the output order follows the smaller collection, not the receiver. So big.intersection(small) and small.intersection(big) contain the same values but may list them differently. If order matters to you, do not rely on the receiver defining it — sort the result, or rebuild it by filtering the collection whose order you want.
Practical use
The everyday job is "which of these does the user also have?" — required tags versus selected tags, requested scopes versus granted scopes. Reading .size on the result answers "how many overlap", and comparing it to zero answers "do they overlap at all" (though isDisjointFrom() says that more directly).
Example
When to use it
- Find which requested OAuth scopes were actually granted
- Show only the tags shared by every selected document
- Check how many required skills a candidate profile covers
- Intersect a large id collection against a short filter list cheaply
Frequently asked questions
What order are the elements of an intersection in?
They follow the smaller of the two collections, because the engine iterates whichever side has fewer elements. Do not assume the receiver dictates order — rebuild by filtering if you need a specific one.
Can I pass an array to intersection()?
No, it throws a TypeError — the argument must be set-like, with size, has() and keys(). Wrap it first: mySet.intersection(new Set(arr)).
How do I just check whether two Sets overlap?
Compare the intersection's size to zero, or use isDisjointFrom(), which answers the question directly and can stop as soon as it finds one shared element.
More examples
Requested versus granted scopes
The intersection is what the client can actually do, and difference() names what was refused. Comparing the two sizes is a compact way to ask whether every requested scope came through.
const requested = new Set(["read", "write", "delete"]);
const granted = new Set(["read", "delete", "billing"]);
const usable = requested.intersection(granted);
console.log([...usable]);
console.log("missing:", [...requested.difference(granted)]);
console.log("all granted?", usable.size === requested.size);Restoring a chosen order
The direct call lists elements in available's order because it is the smaller collection, giving ["b", "a"]. Filtering the spread of wanted forces the order you actually intended, ["a", "b"] as they appear there.
const wanted = new Set(["c", "a", "b", "d"]);
const available = new Set(["b", "a"]);
console.log([...wanted.intersection(available)]);
// Rebuild in the receiver's order
const inWantedOrder = [...wanted].filter((v) => available.has(v));
console.log(inWantedOrder);Overlap tests on non-Set inputs
Passing the raw array throws because arrays expose length rather than size and so are not set-like. Wrapping both sides gives the overlap, and a non-zero size answers whether the two lists touch at all.
const tagsA = ["js", "web", "perf"];
const tagsB = ["perf", "rust"];
try {
new Set(tagsA).intersection(tagsB);
} catch (err) {
console.log(err.constructor.name);
}
const shared = new Set(tagsA).intersection(new Set(tagsB));
console.log([...shared], shared.size > 0);
Discussion