{"record":{"id":"d300a839232b119a","repo":"oxc-project/oxc","slug":"should-be-a-set-and-use-has-to-check-exist","errorCode":null,"errorMessage":"should be a `Set`, and use `.has()` to check existence or non-existence.","messagePattern":"should be a `Set`, and use `\\.has\\(\\)` to check existence or non-existence\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/unicorn/prefer_set_has.rs","lineNumber":35,"sourceCode":"    \"concat\",\n    \"copyWithin\",\n    \"fill\",\n    \"filter\",\n    \"flat\",\n    \"flatMap\",\n    \"map\",\n    \"reverse\",\n    \"slice\",\n    \"sort\",\n    \"splice\",\n    \"toReversed\",\n    \"toSorted\",\n    \"toSpliced\",\n    \"with\",\n];\n\nfn prefer_set_has_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"should be a `Set`, and use `.has()` to check existence or non-existence.\")\n        .with_help(\"Switch to `Set`\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct PreferSetHas;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// `Set#has()` is faster than `Array#includes()`.\n    ///\n    /// ### Examples\n    ///","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/unicorn/prefer_set_has.rs#L17-L53","documentation":"This is the oxlint rule `unicorn/prefer-set-has` (category `perf`, fix marked `dangerous_fix`). It fires when an array is used only for existence checks via `Array#includes()` even though a `Set` with `Set#has()` would do the same job in O(1) instead of O(n). The diagnostic is attached to the array declaration or the `.includes()` usage, telling you the value 'should be a `Set`, and use `.has()`'.","triggerScenarios":"An array built from an array literal, `new Array()`, `Array.from()`, `Array.of()`, or an array-returning method from the tracked list (map/filter/slice/concat/sort/...) whose only meaningful use is `arr.includes(value)` — typically inside a loop or a callback called repeatedly, at the same scope, without intervening mutation (checks via `is_multiple_calls` and scope analysis).","commonSituations":"Membership tests like `const VALID = ['a','b','c']; if (VALID.includes(x))` in hot paths, or generated code migrated from ESLint unicorn configs; also flagged in code reviews where the array is also spread/indexed elsewhere — the auto-fix is dangerous precisely because other usages may still require a real array.","solutions":["Convert the collection to `const set = new Set([...])` and replace `.includes(x)` with `set.has(x)`.","If the value must stay an array (iterated, indexed, deduped order matters, or used with array methods), keep `.includes()` and disable the rule for the line: `// oxlint-disable unicorn/prefer-set-has`.","If flags are pervasive and intentional (small constant arrays where the perf win is negligible), turn the rule off in `.oxlintrc.json`.","Apply the autofix with `oxlint --fix` only after confirming every other usage of the variable tolerates a `Set`."],"exampleFix":"// before\nconst allowed = ['read', 'write', 'admin'];\nconst can = (role) => allowed.includes(role);\n\n// after\nconst allowed = new Set(['read', 'write', 'admin']);\nconst can = (role) => allowed.has(role);","handlingStrategy":"validation","validationCode":"// Pre-check helper: use Set when the collection is only used for membership\nfunction membershipCollection(values) {\n  return new Set(values);\n}\nconst allowed = membershipCollection(['read', 'write']);\nif (allowed.has(role)) { /* ... */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to `Set` for constant lookup collections; only keep arrays when you iterate/index or need duplicates.","Watch for `dangerous_fix`: after `oxlint --fix`, confirm no remaining `.map/.filter/.length` usages on the converted variable.","Gate the rule in CI with `oxlint --deny-warn unicorn/prefer-set-has` on hot-path directories only."],"tags":["oxlint","unicorn","performance","set","array-includes"],"backgroundTag":"set-has-vs-array-includes","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}