[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-set-methods-union-intersection":32,"code:js:true:49khf2":276,"code:js:true:qx05hf":277,"code:js:true:1d5bwi4":278,"code:js:true:1jht4eh":279,"code:js:true:tgijum":280,"code:js:true:1w1m6wi":281,"code:js:true:1jops2s":282,"code:js:true:adae6k":283,"code:js:true:8f2bwc":284,"code:js:true:18dlv1":285,"code:js:true:n26xvk":286,"code:json:true:14ydvc8":287},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":65,"body":67,"bodyMd":258,"seo":259,"translationGroupId":263,"thread":264,"assessments":266,"translations":272,"quiz":274},"019fe660-6e7e-72cb-bd34-bc123056cfeb","set-methods-union-intersection","You've been doing Set math by hand. JavaScript finally shipped `.union()`, `.intersection()`, and friends.",null,"Set has always been missing its obvious operations. ES2025 adds `.union()`, `.intersection()`, `.difference()`, `.symmetricDifference()`, and three boolean predicates — native methods that used to require four lines of spread syntax each.","\u002Fmedia\u002Fcovers\u002Fset-methods-union-intersection.png",4,"2026-07-23T08:37:02.144Z",31,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"javascript","JavaScript",[52,54,57,60],{"slug":49,"name":53,"color":36},"Javascript",{"slug":55,"name":56,"color":36},"webdev","Webdev",{"slug":58,"name":59,"color":36},"frontend","Frontend",{"slug":61,"name":62,"color":36},"typescript","Typescript",{"assessments":64},1,{"slug":34,"title":66},"Set algebra — interactive playground",{"blocks":68,"version":64},[69,73,79,82,85,89,92,95,99,102,106,109,113,116,120,123,126,130,133,137,140,144,147,150,153,156,159,162,165,169,172,176,179,183,186,189,193,196,199,202,207,210,213,216,219,222,225,228,231,234,237,240,243,246,249],{"id":70,"html":71,"type":72},"b1","\u003Cp>You&#39;ve written some version of this:\u003C\u002Fp>","paragraph",{"id":74,"code":75,"type":76,"language":77,"highlight":78},"b2","const intersection = new Set([...setA].filter(x => setB.has(x)));\nconst difference   = new Set([...setA].filter(x => !setB.has(x)));\nconst union        = new Set([...setA, ...setB]);","code","js",[],{"id":80,"html":81,"type":72},"b3","\u003Cp>It works. It&#39;s also four lines of manual iteration for operations any set-theory textbook covers in a sentence. JavaScript&#39;s \u003Ccode>Set\u003C\u002Fcode> shipped in ES6 — ten years ago — but the methods that make sets actually useful didn&#39;t come with it.\u003C\u002Fp>",{"id":83,"html":84,"type":72},"b4","\u003Cp>ES2025 added them. All of them.\u003C\u002Fp>",{"id":86,"html":87,"text":87,"type":88,"level":31},"b5","The seven new methods","heading",{"id":90,"html":91,"type":72},"b6","\u003Cp>Every new \u003Ccode>Set\u003C\u002Fcode> method takes another set-like object — a \u003Ccode>Set\u003C\u002Fcode>, a \u003Ccode>Map\u003C\u002Fcode>, or anything with a \u003Ccode>size\u003C\u002Fcode> property and a \u003Ccode>has\u003C\u002Fcode> method — and returns a new \u003Ccode>Set\u003C\u002Fcode> without modifying either input.\u003C\u002Fp>",{"id":93,"html":94,"type":72},"b7","\u003Cp>\u003Cstrong>\u003Ccode>.union(other)\u003C\u002Fcode>\u003C\u002Fstrong> — all elements from both sets:\u003C\u002Fp>",{"id":96,"code":97,"type":76,"language":77,"highlight":98},"b8","const a = new Set([1, 2, 3]);\nconst b = new Set([3, 4, 5]);\n\na.union(b); \u002F\u002F Set {1, 2, 3, 4, 5}",[],{"id":100,"html":101,"type":72},"b9","\u003Cp>\u003Cstrong>\u003Ccode>.intersection(other)\u003C\u002Fcode>\u003C\u002Fstrong> — only elements present in both:\u003C\u002Fp>",{"id":103,"code":104,"type":76,"language":77,"highlight":105},"b10","a.intersection(b); \u002F\u002F Set {3}",[],{"id":107,"html":108,"type":72},"b11","\u003Cp>\u003Cstrong>\u003Ccode>.difference(other)\u003C\u002Fcode>\u003C\u002Fstrong> — elements in \u003Ccode>this\u003C\u002Fcode> that are not in \u003Ccode>other\u003C\u002Fcode>:\u003C\u002Fp>",{"id":110,"code":111,"type":76,"language":77,"highlight":112},"b12","a.difference(b); \u002F\u002F Set {1, 2}\nb.difference(a); \u002F\u002F Set {4, 5}",[],{"id":114,"html":115,"type":72},"b13","\u003Cp>\u003Cstrong>\u003Ccode>.symmetricDifference(other)\u003C\u002Fcode>\u003C\u002Fstrong> — elements in exactly one of the two sets:\u003C\u002Fp>",{"id":117,"code":118,"type":76,"language":77,"highlight":119},"b14","a.symmetricDifference(b); \u002F\u002F Set {1, 2, 4, 5}",[],{"id":121,"html":122,"type":72},"b15","\u003Cp>These four cover the standard set algebra you reach for most often. The other three are boolean predicates:\u003C\u002Fp>",{"id":124,"html":125,"type":72},"b16","\u003Cp>\u003Cstrong>\u003Ccode>.isSubsetOf(other)\u003C\u002Fcode>\u003C\u002Fstrong> — true if every element of \u003Ccode>this\u003C\u002Fcode> is in \u003Ccode>other\u003C\u002Fcode>:\u003C\u002Fp>",{"id":127,"code":128,"type":76,"language":77,"highlight":129},"b17","new Set([1, 2]).isSubsetOf(new Set([1, 2, 3])); \u002F\u002F true\nnew Set([1, 4]).isSubsetOf(new Set([1, 2, 3])); \u002F\u002F false",[],{"id":131,"html":132,"type":72},"b18","\u003Cp>\u003Cstrong>\u003Ccode>.isSupersetOf(other)\u003C\u002Fcode>\u003C\u002Fstrong> — true if every element of \u003Ccode>other\u003C\u002Fcode> is in \u003Ccode>this\u003C\u002Fcode>:\u003C\u002Fp>",{"id":134,"code":135,"type":76,"language":77,"highlight":136},"b19","new Set([1, 2, 3]).isSupersetOf(new Set([1, 2])); \u002F\u002F true",[],{"id":138,"html":139,"type":72},"b20","\u003Cp>\u003Cstrong>\u003Ccode>.isDisjointFrom(other)\u003C\u002Fcode>\u003C\u002Fstrong> — true if the sets share no elements at all:\u003C\u002Fp>",{"id":141,"code":142,"type":76,"language":77,"highlight":143},"b21","new Set([1, 2]).isDisjointFrom(new Set([3, 4])); \u002F\u002F true\nnew Set([1, 2]).isDisjointFrom(new Set([2, 3])); \u002F\u002F false",[],{"id":145,"html":146,"type":72},"b22","\u003C!-- playground:start -->",{"id":148,"html":149,"text":149,"type":88,"level":31},"b23","🎮 Try it yourself",{"id":151,"html":152,"type":72},"b24","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-07-23-set-methods-union-intersection\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":154,"html":155,"type":72},"b25","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":157,"html":158,"type":72},"b26","\u003C!-- playground:end -->",{"id":160,"html":161,"text":161,"type":88,"level":31},"b27","A real-world example: permission diffing",{"id":163,"html":164,"type":72},"b28","\u003Cp>The operations pay for themselves quickly when you&#39;re comparing sets of strings:\u003C\u002Fp>",{"id":166,"code":167,"type":76,"language":77,"highlight":168},"b29","const currentPermissions = new Set(['read', 'write', 'admin']);\nconst requiredPermissions = new Set(['read', 'write', 'delete']);\n\nconst missing = requiredPermissions.difference(currentPermissions);\n\u002F\u002F Set {'delete'} — what the user needs but doesn't have\n\nconst hasAll = requiredPermissions.isSubsetOf(currentPermissions);\n\u002F\u002F false — deny access",[],{"id":170,"html":171,"type":72},"b30","\u003Cp>Or computing which tags changed between two versions of a document:\u003C\u002Fp>",{"id":173,"code":174,"type":76,"language":77,"highlight":175},"b31","const before = new Set(['react', 'typescript', 'css']);\nconst after  = new Set(['react', 'vue', 'css', 'tailwind']);\n\nconst added   = after.difference(before);      \u002F\u002F Set {'vue', 'tailwind'}\nconst removed = before.difference(after);      \u002F\u002F Set {'typescript'}\nconst stable  = before.intersection(after);    \u002F\u002F Set {'react', 'css'}",[],{"id":177,"html":178,"type":72},"b32","\u003Cp>Before, each of those lines was a three-liner. Now each is one method call that reads exactly like what it computes.\u003C\u002Fp>",{"id":180,"html":181,"text":182,"type":88,"level":31},"b33","The &quot;set-like&quot; argument","The \"set-like\" argument",{"id":184,"html":185,"type":72},"b34","\u003Cp>Each method accepts any \u003Cem>set-like\u003C\u002Fem> object — not just \u003Ccode>Set\u003C\u002Fcode> instances. The spec defines set-like as any object with a numeric \u003Ccode>size\u003C\u002Fcode> property, a \u003Ccode>has(key)\u003C\u002Fcode> method, and a \u003Ccode>keys()\u003C\u002Fcode> method returning an iterator.\u003C\u002Fp>",{"id":187,"html":188,"type":72},"b35","\u003Cp>This means you can pass a \u003Ccode>Map\u003C\u002Fcode> as the argument and it works using the map&#39;s keys:\u003C\u002Fp>",{"id":190,"code":191,"type":76,"language":77,"highlight":192},"b36","const activeUserIds = new Map([['u1', userA], ['u2', userB]]);\nconst bannedIds     = new Set(['u2', 'u3']);\n\nbannedIds.intersection(activeUserIds); \u002F\u002F Set {'u2'}",[],{"id":194,"html":195,"type":72},"b37","\u003Cp>It also means you can build custom data structures that interoperate with the native methods without converting to a plain \u003Ccode>Set\u003C\u002Fcode> first — anything implementing the three-property contract is compatible.\u003C\u002Fp>",{"id":197,"html":198,"text":198,"type":88,"level":31},"b38","TypeScript support",{"id":200,"html":201,"type":72},"b39","\u003Cp>TypeScript added the full method signatures in version 5.5 under the \u003Ccode>ES2025\u003C\u002Fcode> lib. If your \u003Ccode>tsconfig.json\u003C\u002Fcode> targets an earlier version, you&#39;ll see type errors. The fix is adding \u003Ccode>&quot;ES2025&quot;\u003C\u002Fcode> (or the more specific \u003Ccode>&quot;ES2025.Collection&quot;\u003C\u002Fcode>) to your \u003Ccode>lib\u003C\u002Fcode> array:\u003C\u002Fp>",{"id":203,"code":204,"type":76,"language":205,"highlight":206},"b40","{\n  \"compilerOptions\": {\n    \"lib\": [\"DOM\", \"ES2025\"]\n  }\n}","json",[],{"id":208,"html":209,"type":72},"b41","\u003Cp>The algebra methods return \u003Ccode>Set&lt;T&gt;\u003C\u002Fcode> and the predicates return \u003Ccode>boolean\u003C\u002Fcode>. No type assertions or manual casting needed.\u003C\u002Fp>",{"id":211,"html":212,"text":212,"type":88,"level":31},"b42","Browser support",{"id":214,"html":215,"type":72},"b43","\u003Cp>All seven methods are \u003Cstrong>Baseline 2025\u003C\u002Fstrong>: Chrome 122, Firefox 127, Safari 17.4, Node.js 22. Any environment targeting browsers from the last year ships these with no polyfill and no build step.\u003C\u002Fp>",{"id":217,"html":218,"type":72},"b44","\u003Cp>If you need to support older targets, a shim is a few dozen lines — but every major browser in active use today already has them natively.\u003C\u002Fp>",{"id":220,"html":221,"type":72},"b45","\u003C!-- quiz:start -->",{"id":223,"html":224,"text":224,"type":88,"level":31},"b46","🧠 Test yourself",{"id":226,"html":227,"type":72},"b47","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-07-23-set-methods-union-intersection\">Take the 6-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":229,"html":230,"type":72},"b48","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":232,"html":233,"type":72},"b49","\u003C!-- quiz:end -->",{"id":235,"html":236,"text":236,"type":88,"level":31},"b50","The takeaway",{"id":238,"html":239,"type":72},"b51","\u003Cp>Search your codebase for \u003Ccode>filter(x =&gt; otherSet.has(x))\u003C\u002Fcode> or \u003Ccode>new Set([...a, ...b])\u003C\u002Fcode>. Each one is a native Set method written by hand.\u003C\u002Fp>",{"id":241,"html":242,"type":72},"b52","\u003Cp>The new methods aren&#39;t just shorter — they&#39;re clearer. \u003Ccode>.difference()\u003C\u002Fcode> names the operation. A spread with a filter describes the implementation. When both are available, the one that names the operation wins: it reads faster, it refactors cleaner, and it signals intent to the next person in the file. The only reason to reach for the manual version now is a polyfill budget you almost certainly don&#39;t have.\u003C\u002Fp>",{"id":244,"type":245},"b53","divider",{"id":247,"html":248,"type":72},"b54","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":250,"type":251,"items":252,"ordered":18},"b55","list",[253,254,255,256,257],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","You've written some version of this:\n\n```js\nconst intersection = new Set([...setA].filter(x => setB.has(x)));\nconst difference   = new Set([...setA].filter(x => !setB.has(x)));\nconst union        = new Set([...setA, ...setB]);\n```\n\nIt works. It's also four lines of manual iteration for operations any set-theory textbook covers in a sentence. JavaScript's `Set` shipped in ES6 — ten years ago — but the methods that make sets actually useful didn't come with it.\n\nES2025 added them. All of them.\n\n## The seven new methods\n\nEvery new `Set` method takes another set-like object — a `Set`, a `Map`, or anything with a `size` property and a `has` method — and returns a new `Set` without modifying either input.\n\n**`.union(other)`** — all elements from both sets:\n\n```js\nconst a = new Set([1, 2, 3]);\nconst b = new Set([3, 4, 5]);\n\na.union(b); \u002F\u002F Set {1, 2, 3, 4, 5}\n```\n\n**`.intersection(other)`** — only elements present in both:\n\n```js\na.intersection(b); \u002F\u002F Set {3}\n```\n\n**`.difference(other)`** — elements in `this` that are not in `other`:\n\n```js\na.difference(b); \u002F\u002F Set {1, 2}\nb.difference(a); \u002F\u002F Set {4, 5}\n```\n\n**`.symmetricDifference(other)`** — elements in exactly one of the two sets:\n\n```js\na.symmetricDifference(b); \u002F\u002F Set {1, 2, 4, 5}\n```\n\nThese four cover the standard set algebra you reach for most often. The other three are boolean predicates:\n\n**`.isSubsetOf(other)`** — true if every element of `this` is in `other`:\n\n```js\nnew Set([1, 2]).isSubsetOf(new Set([1, 2, 3])); \u002F\u002F true\nnew Set([1, 4]).isSubsetOf(new Set([1, 2, 3])); \u002F\u002F false\n```\n\n**`.isSupersetOf(other)`** — true if every element of `other` is in `this`:\n\n```js\nnew Set([1, 2, 3]).isSupersetOf(new Set([1, 2])); \u002F\u002F true\n```\n\n**`.isDisjointFrom(other)`** — true if the sets share no elements at all:\n\n```js\nnew Set([1, 2]).isDisjointFrom(new Set([3, 4])); \u002F\u002F true\nnew Set([1, 2]).isDisjointFrom(new Set([2, 3])); \u002F\u002F false\n```\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-07-23-set-methods-union-intersection\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n## A real-world example: permission diffing\n\nThe operations pay for themselves quickly when you're comparing sets of strings:\n\n```js\nconst currentPermissions = new Set(['read', 'write', 'admin']);\nconst requiredPermissions = new Set(['read', 'write', 'delete']);\n\nconst missing = requiredPermissions.difference(currentPermissions);\n\u002F\u002F Set {'delete'} — what the user needs but doesn't have\n\nconst hasAll = requiredPermissions.isSubsetOf(currentPermissions);\n\u002F\u002F false — deny access\n```\n\nOr computing which tags changed between two versions of a document:\n\n```js\nconst before = new Set(['react', 'typescript', 'css']);\nconst after  = new Set(['react', 'vue', 'css', 'tailwind']);\n\nconst added   = after.difference(before);      \u002F\u002F Set {'vue', 'tailwind'}\nconst removed = before.difference(after);      \u002F\u002F Set {'typescript'}\nconst stable  = before.intersection(after);    \u002F\u002F Set {'react', 'css'}\n```\n\nBefore, each of those lines was a three-liner. Now each is one method call that reads exactly like what it computes.\n\n## The \"set-like\" argument\n\nEach method accepts any *set-like* object — not just `Set` instances. The spec defines set-like as any object with a numeric `size` property, a `has(key)` method, and a `keys()` method returning an iterator.\n\nThis means you can pass a `Map` as the argument and it works using the map's keys:\n\n```js\nconst activeUserIds = new Map([['u1', userA], ['u2', userB]]);\nconst bannedIds     = new Set(['u2', 'u3']);\n\nbannedIds.intersection(activeUserIds); \u002F\u002F Set {'u2'}\n```\n\nIt also means you can build custom data structures that interoperate with the native methods without converting to a plain `Set` first — anything implementing the three-property contract is compatible.\n\n## TypeScript support\n\nTypeScript added the full method signatures in version 5.5 under the `ES2025` lib. If your `tsconfig.json` targets an earlier version, you'll see type errors. The fix is adding `\"ES2025\"` (or the more specific `\"ES2025.Collection\"`) to your `lib` array:\n\n```json\n{\n  \"compilerOptions\": {\n    \"lib\": [\"DOM\", \"ES2025\"]\n  }\n}\n```\n\nThe algebra methods return `Set\u003CT>` and the predicates return `boolean`. No type assertions or manual casting needed.\n\n## Browser support\n\nAll seven methods are **Baseline 2025**: Chrome 122, Firefox 127, Safari 17.4, Node.js 22. Any environment targeting browsers from the last year ships these with no polyfill and no build step.\n\nIf you need to support older targets, a shim is a few dozen lines — but every major browser in active use today already has them natively.\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 6-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-07-23-set-methods-union-intersection)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n\n## The takeaway\n\nSearch your codebase for `filter(x => otherSet.has(x))` or `new Set([...a, ...b])`. Each one is a native Set method written by hand.\n\nThe new methods aren't just shorter — they're clearer. `.difference()` names the operation. A spread with a filter describes the implementation. When both are available, the one that names the operation wins: it reads faster, it refactors cleaner, and it signals intent to the next person in the file. The only reason to reach for the manual version now is a polyfill budget you almost certainly don't have.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":260,"canonical":261,"description":262},"You've been doing Set math by hand. JavaScript finally shipped `.union","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fset-methods-union-intersection","Set has always been missing its obvious operations. ES2025 adds `.union()`, `.intersection()`, `.difference()`, `.symmetricDifference()`, and three boolean predicates — native meth","019fe660-6e7e-72cb-bd34-c22f5f7ac607",{"id":265,"locked":18},"019fe660-7547-75d2-bdb0-f4677070bcaa",[267],{"id":268,"slug":34,"title":269,"_count":270},"019fe776-7069-74fc-a5e7-5a0fc66dc0c1","Set methods: union, intersection, difference, symmetricDifference",{"questions":271},6,[273],{"locale":13,"slug":34},{"id":268,"slug":34,"title":269,"_count":275,"questionCount":271},{"questions":271},"\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> intersection \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>setA\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">filter\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>x \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> setB\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>x\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> difference   \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>setA\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">filter\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>x \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">!\u003C\u002Fspan>setB\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>x\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> union        \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>setA\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>setB\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> a \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> b \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">4\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">5\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\na\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">union\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {1, 2, 3, 4, 5}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">intersection\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {3}\u003C\u002Fspan>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">difference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {1, 2}\n\u003C\u002Fspan>b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">difference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {4, 5}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">symmetricDifference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {1, 2, 4, 5}\u003C\u002Fspan>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isSubsetOf\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F true\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">4\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isSubsetOf\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F false\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isSupersetOf\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F true\u003C\u002Fspan>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isDisjointFrom\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">4\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F true\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isDisjointFrom\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F false\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> currentPermissions \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'read'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'write'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'admin'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> requiredPermissions \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'read'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'write'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'delete'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> missing \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> requiredPermissions\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">difference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>currentPermissions\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {'delete'} — what the user needs but doesn't have\n\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> hasAll \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> requiredPermissions\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">isSubsetOf\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>currentPermissions\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F false — deny access\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> before \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'react'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'typescript'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'css'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> after  \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'react'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'vue'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'css'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'tailwind'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> added   \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> after\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">difference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>before\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;      \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {'vue', 'tailwind'}\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> removed \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> before\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">difference\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>after\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;      \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {'typescript'}\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> stable  \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> before\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">intersection\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>after\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;    \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {'react', 'css'}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> activeUserIds \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Map\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'u1'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> userA\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'u2'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> userB\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> bannedIds     \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Set\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'u2'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'u3'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nbannedIds\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">intersection\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>activeUserIds\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F Set {'u2'}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-json shj-multiline\" data-lang=\"json\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\"compilerOptions\"\u003C\u002Fspan>: \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\"lib\"\u003C\u002Fspan>: \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"DOM\"\u003C\u002Fspan>, \u003Cspan class=\"shj-str\">\"ES2025\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]