Unicorn
Modernization and style rules from eslint-plugin-unicorn.
They span array iteration, string and regex idioms, Node.js APIs, error handling, module syntax, DOM APIs, and code shape.
They rewrite legacy patterns into modern counterparts, forbid known anti-patterns, and pin a consistent style for things Core and TypeScript leave underspecified.
Most rules are pure AST checks. Binding-aware rules use the TypeScript checker when lexical identity is part of the contract.
Source: eslint-plugin-unicorn (MIT).
Rule index
Each rule name links to the detailed section below.
Examples come from the checked lint corpus or package-level rule tests when project layout matters.
Rules whose native port is registered but intentionally diagnostic-free are marked as illustrative in their detailed section.
Disallow
unicorn/no-abusive-eslint-disable: Require everyeslint-disable*directive to name the rules it disables.unicorn/no-accessor-recursion: Reject recursive reads onthis.<prop>inside the getter / setter for<prop>.unicorn/no-anonymous-default-export: Require a name on every default-exported function, class, or object.unicorn/no-array-callback-reference: Reject passing a function reference directly as the callback tomap/filter/forEach/ etc.unicorn/no-array-for-each: Preferfor...ofoverArray.prototype.forEach.unicorn/no-array-method-this-argument: Reject the secondthisArgargument to array methods.unicorn/no-array-reduce: RejectArray#reduce/Array#reduceRight.unicorn/no-array-reverse: PreferArray#toReversedover the mutatingArray#reverse.unicorn/no-array-sort: PreferArray#toSortedover the mutatingArray#sort.unicorn/no-await-expression-member: Reject member access on anawaitexpression.unicorn/no-await-in-promise-methods: Rejectawaitinside arrays passed toPromise.all/Promise.allSettled/Promise.race/Promise.any.unicorn/no-console-spaces: Reject leading or trailing spaces in arguments toconsole.logand friends.unicorn/no-document-cookie: Reject direct reads or assignments todocument.cookie.unicorn/no-empty-file: Reject source files whose only content is whitespace and/or comments.unicorn/no-for-loop: Preferfor...ofover index-basedforloops over arrays.unicorn/no-hex-escape: Prefer Unicode escape over hexadecimal escape.unicorn/no-immediate-mutation: Reject mutating a value on the same expression.unicorn/no-instanceof-builtins: Rejectinstanceof Array,instanceof Error,instanceof Map, etc., they fail across realms and for subclasses.unicorn/no-invalid-fetch-options: Reject GET / HEADfetch()calls that also set a requestbody.unicorn/no-invalid-remove-event-listener: RejectremoveEventListenercalls whose handler argument is a fresh function reference.unicorn/no-keyword-prefix: Reject identifiers that start with a reserved word.unicorn/no-lonely-if: Rejectifas the only statement inside anelseblock.unicorn/no-magic-array-flat-depth: Reject magic-number depth arguments toArray#flat.unicorn/no-named-default: Reject re-importing or re-exporting a default binding under a name.unicorn/no-negated-condition: Reject negated conditions inif/elseand ternaries.unicorn/no-negation-in-equality-check: Reject!a === b; requirea !== bor!(a === b).unicorn/no-nested-ternary: Reject ternaries nested inside other ternaries.unicorn/no-new-array: Reject thenew Array(...)constructor.unicorn/no-new-buffer: Reject the deprecatednew Buffer()constructor.unicorn/no-null: Reject thenullliteral in favor ofundefined.unicorn/no-object-as-default-parameter: Reject inline object literals as default values for function parameters.unicorn/no-process-exit: Rejectprocess.exit(); throw or return a non-zero status instead.unicorn/no-single-promise-in-promise-methods: RejectPromise.all/Promise.race/ etc. called with a single-element array.unicorn/no-static-only-class: Reject classes whose every member isstatic.unicorn/no-thenable: Reject defining a property namedthenon objects, modules, or classes.unicorn/no-this-assignment: Rejectconst self = thisand similar aliases.unicorn/no-typeof-undefined: Rejecttypeof x === "undefined"; compare againstundefineddirectly.unicorn/no-unnecessary-array-flat-depth: Reject1as the explicit depth argument ofArray#flat.unicorn/no-unnecessary-array-splice-count: Reject.length/Infinityas the deleteCount argument tosplice/toSpliced.unicorn/no-unnecessary-await: Rejectawaiton non-thenable expressions.unicorn/no-unnecessary-polyfills: Reject polyfill imports for APIs already available in the project’s targeted Node / browser baseline.unicorn/no-unnecessary-slice-end: Reject.length/Infinityas the end argument toslice.unicorn/no-unreadable-array-destructuring: Reject destructuring patterns with long hole runs.unicorn/no-unreadable-iife: Reject IIFEs whose nesting is hard to read.unicorn/no-unused-properties: Reject object properties that are never read after definition.unicorn/no-useless-collection-argument: Reject useless initializer arguments on collection constructors.unicorn/no-useless-error-capture-stack-trace: RejectError.captureStackTrace(this, constructor).unicorn/no-useless-fallback-in-spread: Reject...(x ?? {})and similar fallbacks.unicorn/no-useless-iterator-to-array: Reject[...iterator]/Array.from(iterator).unicorn/no-useless-length-check: Rejectarr.lengthchecks that the iteration method itself already handles.unicorn/no-useless-promise-resolve-reject: Rejectreturn Promise.resolve(x)/return Promise.reject(e)insideasyncfunctions.unicorn/no-useless-spread: Reject spreading a single iterable into a new collection of the same kind.unicorn/no-useless-switch-case: Rejectcaseclauses with an empty body that immediately precede adefault.unicorn/no-useless-undefined: Reject explicitundefinedreturns, default initializers, and arguments.unicorn/no-zero-fractions: Reject1.0/1./.5e0in favor of1,1, and0.5.
Prefer
unicorn/prefer-add-event-listener: PreferaddEventListener/removeEventListenerover assigning toon*properties.unicorn/prefer-array-find: PreferArray#find/Array#findLastoverfilter(...)[0]/filter(...).at(-1).unicorn/prefer-array-flat: PreferArray#flatover legacy flattening idioms.unicorn/prefer-array-flat-map: PreferArray#flatMapovermap(...).flat().unicorn/prefer-array-index-of: PreferindexOf/lastIndexOfoverfindIndex/findLastIndex.unicorn/prefer-array-some: PreferArray#someoverfilter(...).length > 0,find(...) !== undefined, and similar shapes.unicorn/prefer-at: PreferArray#at/String#atover index arithmetic andcharAt.unicorn/prefer-bigint-literals: Prefer1noverBigInt(1)andBigInt("1").unicorn/prefer-blob-reading-methods: PreferBlob#arrayBuffer()/Blob#text()overFileReader#readAsArrayBuffer/readAsText.unicorn/prefer-class-fields: Prefer class field declarations over constructor assignments tothis.field = value.unicorn/prefer-classlist-toggle: PreferElement#classList.toggle(name, condition)over manualadd/removebranches.unicorn/prefer-code-point: PreferString#codePointAt/String.fromCodePointovercharCodeAt/fromCharCode.unicorn/prefer-date-now: PreferDate.now()overnew Date().getTime()/+new Date().unicorn/prefer-default-parameters: Prefer default parameter syntax overx = x ?? defaultreassignments inside the function body.unicorn/prefer-dom-node-append: PreferNode#appendoverNode#appendChild.unicorn/prefer-dom-node-dataset: PreferElement#datasetovergetAttribute/setAttributefordata-*attributes.unicorn/prefer-dom-node-remove: PreferChildNode#removeoverparent.removeChild(child).unicorn/prefer-dom-node-text-content: PreferNode#textContentoverHTMLElement#innerText.unicorn/prefer-event-target: PreferEventTargetover Node’sEventEmitter.unicorn/prefer-export-from: Preferexport ... fromover importing-then-re-exporting in two statements.unicorn/prefer-global-this: PreferglobalThisoverwindow,self, andglobal.unicorn/prefer-import-meta-properties: Preferimport.meta.dirname/import.meta.filenameoverfileURLToPathworkarounds.unicorn/prefer-includes: PreferString#includes/Array#includesoverindexOf(...) !== -1andsome(x => x === target).unicorn/prefer-json-parse-buffer: Prefer passing aBufferdirectly toJSON.parse(Node 21+).unicorn/prefer-keyboard-event-key: PreferKeyboardEvent#keyover the deprecatedKeyboardEvent#keyCode/charCode/which.unicorn/prefer-logical-operator-over-ternary: Prefera || b/a ?? bover the equivalent ternary.unicorn/prefer-math-min-max: PreferMath.min/Math.maxover ternaries computing the same value.unicorn/prefer-math-trunc: PreferMath.truncover~~x/x | 0for integer truncation.unicorn/prefer-modern-dom-apis: Preferbefore/after/replaceWithoverinsertBefore/replaceChild/insertAdjacentText.unicorn/prefer-modern-math-apis: PreferMath.log10/Math.hypot/Math.log2/Math.cbrtover their legacy approximations.unicorn/prefer-module: Prefer ES modules over CommonJS.unicorn/prefer-native-coercion-functions: Prefer the bareString/Number/Boolean/BigIntfunctions overx => String(x)arrow wrappers.unicorn/prefer-negative-index: Prefer negative-index lookups overarr.length - 1/arr.length - 2arithmetic.unicorn/prefer-node-protocol: Prefernode:fs/node:path/ etc. over the bare Node builtin specifier.unicorn/prefer-number-properties: PreferNumber.isNaN/Number.parseInt/Number.NaNover their global counterparts.unicorn/prefer-object-from-entries: PreferObject.fromEntriesoverreduce-into-object patterns.unicorn/prefer-optional-catch-binding: Prefercatch { ... }overcatch (e) { ... }.unicorn/prefer-prototype-methods: Prefer borrowing prototype methods over[].slice.callempty-instance lookups.unicorn/prefer-query-selector: PreferDocument#querySelectorovergetElementById,getElementsByClassName, andgetElementsByTagName.unicorn/prefer-reflect-apply: PreferReflect.apply(fn, thisArg, args)overFunction.prototype.apply.call(fn, thisArg, args).unicorn/prefer-regexp-test: PreferRegExp#testoverString#match/RegExp#exec.unicorn/prefer-response-static-json: PreferResponse.json(value).unicorn/prefer-set-has: PreferSet#hasoverArray#includesfor repeated membership lookups against a constant collection.unicorn/prefer-set-size: PreferSet#sizeover[...set].lengthandArray.from(set).length.unicorn/prefer-simple-condition-first: Place identifier and strict-comparison gates before complex conditions in boolean&&/||chains.unicorn/prefer-single-call: Prefer a singlepush/unshift/classList.add/addEventListenerwith multiple arguments.unicorn/prefer-spread: Prefer spread overArray.from,Array.prototype.slice.call,concat([]), andsplit('').unicorn/prefer-string-raw: PreferString.rawfor path literals and other strings.unicorn/prefer-string-replace-all: PreferString#replaceAll(literal, replacement)overreplace(/literal/g, replacement).unicorn/prefer-string-slice: PreferString#sliceover the deprecatedsubstr/substring.unicorn/prefer-string-starts-ends-with: PreferString#startsWith/String#endsWithover equivalentRegExp#testand slice-then-compare idioms.unicorn/prefer-string-trim-start-end: PreferString#trimStart/String#trimEndover the deprecatedtrimLeft/trimRight.unicorn/prefer-structured-clone: PreferstructuredClone(x)overJSON.parse(JSON.stringify(x))for deep cloning.unicorn/prefer-switch: Preferswitchover chains of three or moreelse ifclauses comparing the same discriminant.unicorn/prefer-ternary: Prefer a ternary overif/else.unicorn/prefer-top-level-await: Prefer top-levelawaitover.then/ IIFE wrappers in ES modules.unicorn/prefer-type-error: Require throwingTypeErrorwhen the surroundingifis a runtime type check.
Require
unicorn/require-array-join-separator: Require an explicit separator argument toArray#join.unicorn/require-module-attributes: Require non-emptywith/assertoptions onimport/exportstatements.unicorn/require-module-specifiers: Require a non-empty specifier list on everyimport/exportstatement.unicorn/require-number-to-fixed-digits-argument: Require an explicit digits argument toNumber#toFixed.unicorn/require-post-message-target-origin: Require an explicittargetOriginargument towindow.postMessage.
Consistency
unicorn/consistent-assert: Enforce consistent assertion style when usingnode:assert.unicorn/consistent-date-clone: Prefer passing aDatedirectly to theDateconstructor.unicorn/consistent-destructuring: Once a property is destructured from an object, require subsequent reads to use the destructured binding.unicorn/consistent-empty-array-spread: Require both branches of a ternary spread inside an array literal.unicorn/consistent-existence-index-check: Compare aconstindex against the-1sentinel instead of against zero.unicorn/consistent-function-scoping: Hoist function declarations to the highest scope.unicorn/consistent-template-literal-escape: Enforce a consistent style when escaping${in template literals.
Other checks
unicorn/better-regex: Rewrite regex literals into shorter, consistent, and safer form.unicorn/catch-error-name: Enforce a canonical parameter name incatchclauses.unicorn/custom-error-definition: Require user-definedErrorsubclasses to setname, callsuper(message), and assign their stack correctly.unicorn/empty-brace-spaces: Reject whitespace inside empty{}braces.unicorn/error-message: Require a non-emptymessageargument.unicorn/escape-case: Require consistent case for escape sequences.unicorn/expiring-todo-comments: Require everyTODO/FIXME/XXXcomment to declare an expiration date or package version.unicorn/explicit-length-check: Require explicit comparison of.length/.size.unicorn/filename-case: Enforce a single case style (kebab / camel / snake / pascal) for source filenames and directory names.unicorn/import-style: Restrict each module’s allowed import styles.unicorn/isolated-functions: Reject references to outer-scope variables inside functions marked as isolated.unicorn/new-for-builtins: Requirenewwhen calling builtin constructors likeError,Map,Set,Date.unicorn/number-literal-case: Enforce one consistent case for a numeric literal’s prefix, hex digits, and exponent.unicorn/numeric-separators-style: Enforce_separator grouping in numeric literals.unicorn/prevent-abbreviations: Apply canonical replacement semantics to bindings, compound names, opt-in property checks, and filenames.unicorn/relative-url-style: Enforce a single style for relative URLs passed tonew URL.unicorn/string-content: Rewrite configured patterns inside string literals and template quasis.unicorn/switch-case-braces: Enforce a consistent presence/absence of{}braces aroundcaseclauses insideswitch.unicorn/switch-case-break-position: Require terminating statements to sit inside acaseclause’s sole block.unicorn/template-indent: Normalize selected multiline template bodies while preserving substitutions and raw escapes.unicorn/text-encoding-identifier-case: Enforce a canonical case for text-encoding identifiers — the dash-less"utf8"by default.unicorn/throw-new-error: Requirethrow new Error(...)overthrow Error(...).
Rules
unicorn/better-regex
Rewrite regex literals into shorter, consistent, and safer form (character-class shorthands, redundant ranges).
Each regex literal is optimized the way regexp-tree canonicalizes it: character classes collapse to their shorthands ([0-9] → \d, [^A-Za-z0-9_] → \W), ranges are deduplicated and sorted, flags are alphabetized, and redundant quantifiers merge (\s?\s?\s? → \s{0,3}). The autofix replaces the whole literal, except when it is the object of a .source or .toString member access — those are reported without a fix so a serialized-source consumer is not rewritten under it. Literals carrying the u or v flag are skipped, matching upstream, because regexp-tree does not handle Unicode / Unicode-sets mode reliably. A new RegExp("pattern", "flags") string constructor rewrites its pattern argument through the same character-class shorthands; the rewritten pattern keeps the argument’s original quote character and is re-escaped for it, so a pattern carrying a newline, a control character, or the delimiter quote comes back as a valid string literal.
The one option, sortCharacterClasses (default true), turns off only the class range sort/merge step when set to false; the length-reducing shorthands still apply.
Example:
// reports: unicorn/better-regex (error) — /[0-9]/ can be optimized to /\d/
const digits = /[0-9]/;export default {
rules: {
"unicorn/better-regex": ["error", { sortCharacterClasses: false }],
},
};unicorn/catch-error-name
Enforce a canonical parameter name (error) in catch clauses.
Example:
// reports: unicorn/catch-error-name (error)
try {
} catch (err) {
void err;
}unicorn/consistent-assert
Enforce consistent assertion style when using node:assert.
Example:
import assert from "node:assert";
// reports: unicorn/consistent-assert (error)
assert.equal(1, 1);unicorn/consistent-date-clone
Prefer passing a Date directly to the Date constructor when cloning, not +date or date.getTime().
Example:
const original = new Date();
// reports: unicorn/consistent-date-clone (error)
const clone = new Date(original.getTime());unicorn/consistent-destructuring
Once a property is destructured from an object, require subsequent reads to use the destructured binding.
Example:
const user = { profile: { name: "Ada" } };
const { profile } = user;
// reports: unicorn/consistent-destructuring (error)
console.log(user.profile.name);unicorn/consistent-empty-array-spread
Require both branches of a ternary spread inside an array literal to be array-typed.
Example:
const cond = true;
const x = 1;
// reports: unicorn/consistent-empty-array-spread (error)
const a = [1, ...(cond ? [x] : 2)];unicorn/consistent-existence-index-check
Compare an index against the -1 sentinel instead of against zero. On a const bound to indexOf, lastIndexOf, findIndex, or findLastIndex, the rule rewrites index < 0 to index === -1, and index >= 0 / index > -1 to index !== -1.
Example:
const arr = [1, 2, 3];
const index = arr.indexOf(2);
// reports: unicorn/consistent-existence-index-check (error)
const found = index >= 0;Only a comparison on a const index binding is reported, matching the upstream rule. An inline arr.indexOf(2) >= 0 binds no index and is left alone, as is an index declared with let or var.
unicorn/consistent-function-scoping
Hoist function declarations to the highest scope that does not capture any outer variables.
Example:
function formatNames(names: string[]) {
// reports: unicorn/consistent-function-scoping (error)
function normalize(name: string) {
return name.trim().toLowerCase();
}
return names.map(normalize);
}The rule checks arrow functions by default. Set checkArrowFunctions: false in the rule options to restrict diagnostics to function declarations and function expressions. Functions that capture an enclosing binding, lexical this, arguments, super, or a private name remain in their current scope.
unicorn/consistent-template-literal-escape
Enforce the \${ spelling over $\{ when escaping ${ in template literals. Both spellings cook to the same text, so the rule canonicalizes on the dollar escape and the autofix rewrites $\{ and \$\{ in place. Tagged templates are skipped because the tag function observes the raw text.
Example:
// reports: unicorn/consistent-template-literal-escape (error)
const template = `Use \${name}, not $\{name}.`;unicorn/custom-error-definition
Require user-defined Error subclasses to set name, call super(message), and assign their stack correctly.
Example:
// reports: unicorn/custom-error-definition (error)
class MyError extends Error {
constructor() {
void 0;
}
}unicorn/empty-brace-spaces
Reject whitespace inside empty {} braces.
Example:
// reports: unicorn/empty-brace-spaces (error)
const o = {};unicorn/error-message
Require a non-empty message argument when constructing a built-in Error.
Example:
// reports: unicorn/error-message (error)
throw new Error();unicorn/escape-case
Require consistent case for escape sequences (\xA9 over \xa9, \u00B5 over \u00b5).
Escapes are read from the raw source of string literals and of every template segment, including the segments of an interpolated template. An escaped backslash opens no escape, so "\\xa9" is left alone, and an escape ends after its digits, so the letters trailing the canonical "\x41bcd" are not part of it. Tagged templates are skipped because the tag function observes the raw text.
Example:
// reports: unicorn/escape-case (error)
const s = "\xa9";unicorn/expiring-todo-comments
Require every TODO/FIXME/XXX comment to declare an expiration date or package version.
Example:
// reports: unicorn/expiring-todo-comments (error)
// TODO: remove the legacy branch after migration.
export const legacyMode = true;unicorn/explicit-length-check
Require explicit comparison of .length / .size instead of relying on truthy coercion.
Example:
const xs = [1, 2, 3];
if (
// reports: unicorn/explicit-length-check (error)
xs.length
) {
void 0;
}unicorn/filename-case
Enforce a single case style (kebab / camel / snake / pascal) for source filenames and directory names.
Every segment of a file’s project-relative path is checked — directories first, then the filename, then a lowercase check on the file extension — and the first offending segment produces the file’s single diagnostic with concrete rename samples. Files outside the project directory are judged by basename alone. $-prefixed segments, the default index.js / index.mjs / index.cjs / index.ts / index.tsx / index.vue basenames, and characters outside [a-zA-Z0-9_-] are exempt from case conversion.
The option object supports case (one enforced style: kebabCase — the default — camelCase, camelCaseWithAcronyms, snakeCase, or pascalCase), cases (a map of allowed styles; case and cases are mutually exclusive, and enabling none falls back to kebab-case), ignore (regular-expression strings matched against each path segment), multipleFileExtensions (default true: only the stem before the first dot is checked), and checkDirectories (default true).
Example:
// File: src/UserProfile.ts
// reports: unicorn/filename-case (error)
// Filename is not in kebab case. Rename it to `user-profile.ts`.
export function renderUserProfile() {}export default {
rules: {
"unicorn/filename-case": [
"error",
{
cases: { kebabCase: true, pascalCase: true },
ignore: ["^vendor-"],
},
],
},
};unicorn/import-style
Restrict each module’s allowed import styles (named only, default only, namespace only).
Every reference to a configured module — static import, dynamic import(), require(…), and (opt-in) export … from — is classified into the styles it actually uses (unassigned, default, namespace, named) and reported when any of them falls outside the module’s allowed set. node:-prefixed specifiers inherit the bare module name’s policy. The built-in table allows only default imports of chalk and path and only named imports of util.
The option object supports styles (per-module maps of style-name booleans, or false to lift a module’s restrictions), extendDefaultStyles, and the checkImport, checkDynamicImport, checkExportFrom, and checkRequire toggles. checkExportFrom defaults to false; the other toggles default to true. For require, an allowed default style also accepts whole-object bindings because CommonJS offers no interop that distinguishes them.
Example:
// reports: unicorn/import-style (error) — use named import for module `util`
import util from "node:util";export default {
rules: {
"unicorn/import-style": [
"error",
{
styles: {
lodash: { named: true },
react: { default: true, named: true },
path: false,
},
},
],
},
};unicorn/isolated-functions
Reject references to outer-scope variables (and this / super) inside functions that run outside their defining context. Functions are recognized as isolated when passed to a configured name (makeSynchronous and workerize by default), to browser.execute / page.evaluate, as the func property of chrome.scripting.executeScript / browser.scripting.executeScript, or when preceded by an @isolated comment; the functions, selectors, comments, and overrideGlobals options tune this.
Example:
const prefix = "user:";
// `makeSynchronous` runs the callback in a separate context, so the captured
// `prefix` is unavailable there.
// reports: unicorn/isolated-functions (error)
const build = makeSynchronous(() => `${prefix}ready`);unicorn/new-for-builtins
Require new when calling builtin constructors like Error, Map, Set, Date, and forbid new on primitive wrappers like String, Number, Boolean.
Example:
// reports: unicorn/new-for-builtins (error)
const xs = Array(3);unicorn/no-abusive-eslint-disable
Require every eslint-disable* directive to name the rules it disables.
Example:
// reports: unicorn/no-abusive-eslint-disable (error)
// eslint-disable-next-line
const _x = 0;unicorn/no-accessor-recursion
Reject recursive reads on this.<prop> inside the getter / setter for <prop>.
Example:
class C {
get value() {
// reports: unicorn/no-accessor-recursion (error)
return this.value;
}
}unicorn/no-anonymous-default-export
Require a name on every default-exported function, class, or object.
Example:
// reports: unicorn/no-anonymous-default-export (error)
export default function () {
return 1;
}unicorn/no-array-callback-reference
Reject passing a function reference directly as the callback to map / filter / forEach / etc., which silently leaks extra index/array arguments to the callee.
Example:
function isEven(n: number) {
return n % 2 === 0;
}
// reports: unicorn/no-array-callback-reference (error)
const evens = [1, 2, 3].filter(isEven);unicorn/no-array-for-each
Prefer for...of over Array.prototype.forEach.
Example:
// reports: unicorn/no-array-for-each (error)
[1, 2, 3].forEach((x) => {
console.log(x);
});unicorn/no-array-method-this-argument
Reject the second thisArg argument to array methods; use an explicit closure instead.
Example:
// reports: unicorn/no-array-method-this-argument (error)
[1, 2].forEach(
function (x) {
console.log(this, x);
},
{ tag: "ctx" },
);unicorn/no-array-reduce
Reject Array#reduce / Array#reduceRight in favor of explicit loops or other helpers.
Example:
// reports: unicorn/no-array-reduce (error)
const total = [1, 2, 3].reduce((a, b) => a + b, 0);unicorn/no-array-reverse
Prefer Array#toReversed over the mutating Array#reverse.
Example:
// reports: unicorn/no-array-reverse (error)
const r = [1, 2, 3].reverse();unicorn/no-array-sort
Prefer Array#toSorted over the mutating Array#sort.
Example:
// reports: unicorn/no-array-sort (error)
const s = [3, 1, 2].sort();unicorn/no-await-expression-member
Reject member access on an await expression without parens; require (await x).y.
Example:
async function f() {
// reports: unicorn/no-await-expression-member (error)
return (await Promise.resolve({ a: 1 })).a;
}unicorn/no-await-in-promise-methods
Reject await inside arrays passed to Promise.all / Promise.allSettled / Promise.race / Promise.any, the awaits serialize the calls.
Example:
async function f() {
// reports: unicorn/no-await-in-promise-methods (error)
await Promise.all([await Promise.resolve(1), Promise.resolve(2)]);
}unicorn/no-console-spaces
Reject leading or trailing spaces in arguments to console.log and friends, console already inserts spaces between args.
Example:
// reports: unicorn/no-console-spaces (error)
console.log("hello ", "world");unicorn/no-document-cookie
Reject direct reads or assignments to document.cookie; use the Cookie Store API or a wrapper.
Example:
// reports: unicorn/no-document-cookie (error)
document.cookie = "name=value";unicorn/no-empty-file
Reject source files whose only content is whitespace and/or comments.
Example:
// reports: unicorn/no-empty-file (error)
;unicorn/no-for-loop
Prefer for...of over index-based for loops over arrays.
Example:
const xs = [1, 2, 3];
// reports: unicorn/no-for-loop (error)
for (let i = 0; i < xs.length; i++) {
void xs[i];
}unicorn/no-hex-escape
Prefer Unicode escape (\u00A9) over hexadecimal escape (\xA9).
Escapes are read from the raw source of string literals and of every template segment, including the segments of an interpolated template. An escaped backslash opens no escape, so "\\x64" is left alone. Tagged templates are skipped because the tag function observes the raw text.
Example:
// reports: unicorn/no-hex-escape (error)
const s = "\xA9";unicorn/no-immediate-mutation
Reject mutating a value on the same expression that produces it ([...x].push(y)); separate the construction and the mutation.
Example:
// reports: unicorn/no-immediate-mutation (error)
const last = [1, 2, 3].push(4);unicorn/no-instanceof-builtins
Reject instanceof Array, instanceof Error, instanceof Map, etc., they fail across realms and for subclasses.
Example:
const x: unknown = [];
// reports: unicorn/no-instanceof-builtins (error)
if (x instanceof Array) {
void x;
}unicorn/no-invalid-fetch-options
Reject GET / HEAD fetch() calls that also set a request body, which throws at runtime.
Example:
// reports: unicorn/no-invalid-fetch-options (error)
fetch("https://example.com", { method: "GET", body: "x" });unicorn/no-invalid-remove-event-listener
Reject removeEventListener calls whose handler argument is a fresh function reference and therefore matches no registered listener.
Example:
const el = new EventTarget();
// reports: unicorn/no-invalid-remove-event-listener (error)
el.removeEventListener("click", () => {});unicorn/no-keyword-prefix
Reject identifiers that start with a reserved word (newFoo, classBar).
Example:
// reports: unicorn/no-keyword-prefix (error)
const newFoo = 1;unicorn/no-lonely-if
Reject if as the only statement inside an else block; use else if instead.
Example:
if (1 === 1) {
void 0;
} else {
// reports: unicorn/no-lonely-if (error)
if (2 === 2) {
void 0;
}
}unicorn/no-magic-array-flat-depth
Reject magic-number depth arguments to Array#flat; require Infinity or a named constant.
Example:
// reports: unicorn/no-magic-array-flat-depth (error)
const flat = [1, [2, [3]]].flat(2);unicorn/no-named-default
Reject re-importing or re-exporting a default binding under a name that differs from the upstream binding.
Example:
// reports: unicorn/no-named-default (error)
import { default as React } from "react";unicorn/no-negated-condition
Reject negated conditions in if/else and ternaries when the positive form is shorter.
Example:
const x = 1;
// reports: unicorn/no-negated-condition (error)
if (x !== 0) {
void "nonzero";
} else {
void "zero";
}unicorn/no-negation-in-equality-check
Reject !a === b; require a !== b or !(a === b).
Example:
const a = 1;
const b = 2;
// reports: unicorn/no-negation-in-equality-check (error)
const eq = !a === b;unicorn/no-nested-ternary
Reject ternaries nested inside other ternaries.
Example:
const x = 1;
// reports: unicorn/no-nested-ternary (error)
const r = x === 0 ? "zero" : x > 0 ? "pos" : "neg";unicorn/no-new-array
Reject the new Array(...) constructor; use array literals or Array.from / Array.of.
Example:
// reports: unicorn/no-new-array (error)
const a = new Array(3);unicorn/no-new-buffer
Reject the deprecated new Buffer() constructor; use Buffer.from or Buffer.alloc.
Example:
// reports: unicorn/no-new-buffer (error)
const b = new Buffer(10);unicorn/no-null
Reject the null literal in favor of undefined.
Example:
// reports: unicorn/no-null (error)
const x = null;unicorn/no-object-as-default-parameter
Reject inline object literals as default values for function parameters.
Example:
// reports: unicorn/no-object-as-default-parameter (error)
function f(opts = { tag: "default" }) {
void opts;
}unicorn/no-process-exit
Reject process.exit(); throw or return a non-zero status instead.
Example:
// reports: unicorn/no-process-exit (error)
process.exit(1);unicorn/no-single-promise-in-promise-methods
Reject Promise.all / Promise.race / etc. called with a single-element array; the wrapper is redundant.
Example:
// reports: unicorn/no-single-promise-in-promise-methods (error)
const p = Promise.all([Promise.resolve(1)]);unicorn/no-static-only-class
Reject classes whose every member is static; use a plain module-level namespace instead.
Example:
// reports: unicorn/no-static-only-class (error)
class Utility {
static helper() {
return 42;
}
}unicorn/no-thenable
Reject defining a property named then on objects, modules, or classes, await and Promise resolution accidentally invoke it.
Example:
const o = {
// reports: unicorn/no-thenable (error)
then() {
return 1;
},
};unicorn/no-this-assignment
Reject const self = this and similar aliases; capture via arrow functions instead.
Example:
class C {
m() {
// reports: unicorn/no-this-assignment (error)
const self = this;
return self;
}
}unicorn/no-typeof-undefined
Reject typeof x === "undefined"; compare against undefined directly.
Only a typeof on the left of an equality comparison (===, ==, !==, !=) against the string literal "undefined" is reported. A reversed "undefined" === typeof x, a template-literal operand (typeof x === `undefined`), and a global operand are all left alone, matching upstream: rewriting typeof window === "undefined" to window === undefined throws a ReferenceError when the global is undeclared. A global here means an identifier that resolves to no local binding. Enable checkGlobalVariables to also check global operands, which are then offered an opt-in suggestion rather than an automatic fix.
The autofix removes the typeof, upgrades == / != to their strict form, and replaces the literal, but declines rather than risk an incorrect edit when removing typeof could trigger Automatic Semicolon Insertion (the operand starts on a different line, or begins with a character that could merge with the preceding token).
Example:
let value: unknown;
// reports: unicorn/no-typeof-undefined (error)
typeof value === "undefined";unicorn/no-unnecessary-array-flat-depth
Reject 1 as the explicit depth argument of Array#flat; the default is already 1.
Example:
// reports: unicorn/no-unnecessary-array-flat-depth (error)
const flat = [1, [2]].flat(1);unicorn/no-unnecessary-array-splice-count
Reject .length / Infinity as the deleteCount argument to splice / toSpliced; omit it to delete to the end.
Example:
const arr = [1, 2, 3];
// reports: unicorn/no-unnecessary-array-splice-count (error)
arr.splice(0, arr.length);unicorn/no-unnecessary-await
Reject await on non-thenable expressions.
Example:
async function f() {
// reports: unicorn/no-unnecessary-await (error)
const x = await 42;
}unicorn/no-unnecessary-polyfills
Reject polyfill imports for APIs already available in the project’s targeted Node / browser baseline.
Every static import, dynamic import(), and static require(…) of a bare specifier is matched against the polyfill packages tracked by core-js-compat (both the core-js / core-js-pure submodule entries and standalone packages like object-assign, es6-promise, array.prototype.flat, mdn-polyfills/*, polyfill-*). The import is reported only when every targeted runtime already ships the feature natively.
The target environments are resolved in the same order as the upstream rule:
- The
targetsoption, when present — a Browserslist query string, an array of queries, or a Browserslist targets object (for example{ "node": "18" }). Query forms are resolved under theproductionenvironment. - Otherwise, standard Browserslist config discovery from the linted file’s directory: a
browserslist/.browserslistrcfile, apackage.jsonbrowserslistfield or section, custombrowserslist-stats.json, and theBROWSERSLIST*environment overrides. - Otherwise, the
enginesfield of the nearestpackage.json.
When no targets can be resolved the rule stays silent. Queries that need inputs the native lint host cannot supply (extends <pkg>, supports <feature>, regional in XX usage, baseline …, and current node) are treated the same way and leave the rule silent for that file. The compatibility dataset is generated from pinned upstream package versions; see packages/lint/tools/polyfilldata/generate.mjs for provenance.
Example:
import "core-js/features/array/at"; // reports when every target already has Array#atexport default {
rules: {
"unicorn/no-unnecessary-polyfills": [
"error",
{
targets: { node: "18" },
},
],
},
};unicorn/no-unnecessary-slice-end
Reject .length / Infinity as the end argument to slice; omit it to slice to the end.
Example:
const arr = [1, 2, 3];
// reports: unicorn/no-unnecessary-slice-end (error)
const c = arr.slice(0, arr.length);unicorn/no-unreadable-array-destructuring
Reject destructuring patterns with long hole runs ([,,,,a]); use a named index instead.
Example:
// reports: unicorn/no-unreadable-array-destructuring (error)
const [, , , , a] = [1, 2, 3, 4, 5];unicorn/no-unreadable-iife
Reject IIFEs whose nesting (multiple parens, arrow IIFE arguments) is hard to read.
Example:
// reports: unicorn/no-unreadable-iife (error)
const r = (() => Math.random())();unicorn/no-unused-properties
Reject object properties that are never read after definition.
The rule follows every reference to a variable bound to an object literal (or annotated with an inline {...} type, including function parameters) and reports the properties no reference can reach. Static accesses must name the key, destructuring must bind it, and matching references recurse into nested objects. Any escape — aliasing, passing, returning, spreading, exporting, mutating, or a dynamic key access — conservatively keeps every property.
Example:
const user = {
id: "u_1",
// reports: unicorn/no-unused-properties (error)
debugLabel: "local-only",
};
console.log(user.id);unicorn/no-useless-collection-argument
Reject useless initializer arguments (new Set(), new Map([]), new Set(undefined)) on collection constructors.
Example:
// reports: unicorn/no-useless-collection-argument (error)
const s = new Set([]);unicorn/no-useless-error-capture-stack-trace
Reject Error.captureStackTrace(this, constructor) when the surrounding subclass relies on the default Error capture.
Example:
class MyError extends Error {
constructor(msg: string) {
super(msg);
// reports: unicorn/no-useless-error-capture-stack-trace (error)
Error.captureStackTrace(this, MyError);
}
}
void new MyError("x");unicorn/no-useless-fallback-in-spread
Reject ...(x ?? {}) and similar fallbacks when spreading; the spread of null / undefined is already a no-op.
Example:
const x: { a: number } | null = null;
// reports: unicorn/no-useless-fallback-in-spread (error)
const o = { ...(x ?? {}) };unicorn/no-useless-iterator-to-array
Reject [...iterator] / Array.from(iterator) when the iterator can be consumed directly (e.g., inside for...of).
Example:
const arr = [1, 2];
// reports: unicorn/no-useless-iterator-to-array (error)
for (const e of [...arr.entries()]) {
void e;
}unicorn/no-useless-length-check
Reject arr.length checks that the iteration method itself already handles.
Example:
const xs = [1, 2, 3];
// reports: unicorn/no-useless-length-check (error)
const hasPositive = xs.length > 0 && xs.some((x) => x > 0);unicorn/no-useless-promise-resolve-reject
Reject return Promise.resolve(x) / return Promise.reject(e) inside async functions, return x and throw e work identically.
Example:
async function f() {
// reports: unicorn/no-useless-promise-resolve-reject (error)
return Promise.resolve(1);
}unicorn/no-useless-spread
Reject spreading a single iterable into a new collection of the same kind ([...arr], {...obj}) when the original would suffice.
Example:
// reports: unicorn/no-useless-spread (error)
const a = [...[1, 2, 3]];unicorn/no-useless-switch-case
Reject case clauses with an empty body that immediately precede a default whose body executes for them.
Example:
const x = 2;
switch (x) {
case 1:
void 0;
break;
// reports: unicorn/no-useless-switch-case (error)
case 2:
default:
void 0;
}unicorn/no-useless-undefined
Reject explicit undefined returns, default initializers, and arguments where the omission has the same meaning.
Example:
function f() {
// reports: unicorn/no-useless-undefined (error)
return undefined;
}unicorn/no-zero-fractions
Reject 1.0 / 1. / .5e0 in favor of 1, 1, and 0.5.
Example:
// reports: unicorn/no-zero-fractions (error)
const n = 1.0;unicorn/number-literal-case
Enforce one consistent case for every letter of a numeric literal: a lowercase radix prefix (0x, 0b, 0o), uppercase hex digits, and a lowercase exponent (0xFF over 0xff, 1e10 over 1E10). BigInt literals are covered too, and their n suffix stays lowercase (0xFFn). The autofix rewrites the literal in place. Only letter case changes, so the value is preserved.
Example:
// reports: unicorn/number-literal-case (error)
const n = 1E10;unicorn/numeric-separators-style
Enforce _ separator grouping (every 3 digits for decimal, every 4 for hex) in numeric literals.
Example:
// reports: unicorn/numeric-separators-style (error)
const big = 1_2345;unicorn/prefer-add-event-listener
Prefer addEventListener / removeEventListener over assigning to on* properties.
Example:
const el = document.querySelector("button")!;
// reports: unicorn/prefer-add-event-listener (error)
el.onclick = () => {};unicorn/prefer-array-find
Prefer Array#find / Array#findLast over filter(...)[0] / filter(...).at(-1).
Example:
const xs = [1, 2, 3];
// reports: unicorn/prefer-array-find (error)
const first = xs.filter((x) => x > 1)[0];unicorn/prefer-array-flat
Prefer Array#flat over legacy flattening idioms ([].concat(...arrs), reduce with concat).
Example:
// reports: unicorn/prefer-array-flat (error)
const flat = [].concat([1, 2], [3, 4]);unicorn/prefer-array-flat-map
Prefer Array#flatMap over map(...).flat().
Example:
// reports: unicorn/prefer-array-flat-map (error)
const result = [1, 2].map((x) => [x, x]).flat();unicorn/prefer-array-index-of
Prefer indexOf / lastIndexOf over findIndex / findLastIndex when matching by ===.
Example:
const xs = [1, 2, 3];
// reports: unicorn/prefer-array-index-of (error)
const i = xs.findIndex((x) => x === 2);unicorn/prefer-array-some
Prefer Array#some over filter(...).length > 0, find(...) !== undefined, and similar shapes.
Example:
const xs = [1, 2, 3];
// reports: unicorn/prefer-array-some (error)
const hasLarge = xs.filter((x) => x > 1).length > 0;unicorn/prefer-at
Prefer Array#at / String#at over negative index arithmetic when the indexed value and the .length receiver are the same runtime reference. Receiver mismatches are left unchanged because .at(-N) would select a different element.
Example:
const xs = [1, 2, 3];
// reports: unicorn/prefer-at (error)
const last = xs[xs.length - 1];
const limits = [0, 1];
const unchanged = xs[limits.length - 1];unicorn/prefer-bigint-literals
Prefer 1n over BigInt(1) and BigInt("1").
Example:
// reports: unicorn/prefer-bigint-literals (error)
const big = BigInt(1);unicorn/prefer-blob-reading-methods
Prefer Blob#arrayBuffer() / Blob#text() over FileReader#readAsArrayBuffer / readAsText.
Example:
const reader = new FileReader();
const blob = new Blob(["hello"]);
// reports: unicorn/prefer-blob-reading-methods (error)
reader.readAsArrayBuffer(blob);unicorn/prefer-class-fields
Prefer class field declarations over constructor assignments to this.field = value.
Example:
class C {
field: number;
constructor() {
// reports: unicorn/prefer-class-fields (error)
this.field = 1;
}
}unicorn/prefer-classlist-toggle
Prefer Element#classList.toggle(name, condition) over manual add / remove branches.
Example:
const el = document.createElement("button");
const cond = true;
// reports: unicorn/prefer-classlist-toggle (error)
if (cond) {
el.classList.add("active");
} else {
el.classList.remove("active");
}unicorn/prefer-code-point
Prefer String#codePointAt / String.fromCodePoint over charCodeAt / fromCharCode.
Example:
// reports: unicorn/prefer-code-point (error)
const code = "a".charCodeAt(0);unicorn/prefer-date-now
Prefer Date.now() over new Date().getTime() / +new Date().
Example:
// reports: unicorn/prefer-date-now (error)
const t = new Date().getTime();unicorn/prefer-default-parameters
Prefer default parameter syntax over x = x ?? default reassignments inside the function body.
Example:
function f(name?: string) {
// reports: unicorn/prefer-default-parameters (error)
name = name ?? "guest";
return name;
}unicorn/prefer-dom-node-append
Prefer Node#append over Node#appendChild.
Example:
const parent = document.createElement("div");
const child = document.createElement("span");
// reports: unicorn/prefer-dom-node-append (error)
parent.appendChild(child);unicorn/prefer-dom-node-dataset
Prefer Element#dataset over getAttribute / setAttribute for data-* attributes.
Example:
const el = document.createElement("div");
// reports: unicorn/prefer-dom-node-dataset (error)
el.getAttribute("data-user-id");unicorn/prefer-dom-node-remove
Prefer ChildNode#remove over parent.removeChild(child).
Example:
const parent = document.createElement("div");
const child = document.createElement("span");
// reports: unicorn/prefer-dom-node-remove (error)
parent.removeChild(child);unicorn/prefer-dom-node-text-content
Prefer Node#textContent over HTMLElement#innerText.
Example:
const el = document.createElement("div");
// reports: unicorn/prefer-dom-node-text-content (error)
el.innerText;unicorn/prefer-event-target
Prefer EventTarget over Node’s EventEmitter when the code is shared between Node and the browser.
Example:
import { EventEmitter } from "node:events";
// reports: unicorn/prefer-event-target (error)
const em = new EventEmitter();unicorn/prefer-export-from
Prefer export ... from over importing-then-re-exporting in two statements.
Example:
import { useState } from "react";
// reports: unicorn/prefer-export-from (error)
export { useState };unicorn/prefer-global-this
Prefer globalThis over window, self, and global.
Example:
// reports: unicorn/prefer-global-this (error)
const root = window;unicorn/prefer-import-meta-properties
Prefer import.meta.dirname / import.meta.filename over fileURLToPath workarounds.
Example:
import { fileURLToPath } from "node:url";
// reports: unicorn/prefer-import-meta-properties (error)
const filename = fileURLToPath(import.meta.url);unicorn/prefer-includes
Prefer String#includes / Array#includes over indexOf(...) !== -1 and some(x => x === target).
Example:
const arr = [1, 2, 3];
// reports: unicorn/prefer-includes (error)
const found = arr.indexOf(2) !== -1;unicorn/prefer-json-parse-buffer
Prefer passing a Buffer directly to JSON.parse (Node 21+) instead of decoding to a string first.
Example:
const buf = Buffer.from('{"ok":true}');
// reports: unicorn/prefer-json-parse-buffer (error)
const data = JSON.parse(buf.toString());unicorn/prefer-keyboard-event-key
Prefer KeyboardEvent#key over the deprecated KeyboardEvent#keyCode / charCode / which.
Example:
const event = new KeyboardEvent("keydown");
// reports: unicorn/prefer-keyboard-event-key (error)
const code = event.keyCode;unicorn/prefer-logical-operator-over-ternary
Prefer a || b / a ?? b over the equivalent ternary a ? a : b.
Example:
const x: number | undefined = 1;
// reports: unicorn/prefer-logical-operator-over-ternary (error)
const y = x ? x : 0;unicorn/prefer-math-min-max
Prefer Math.min / Math.max over ternaries computing the same value.
Example:
const a = 1;
const b = 2;
// reports: unicorn/prefer-math-min-max (error)
const m = a < b ? a : b;unicorn/prefer-math-trunc
Prefer Math.trunc over ~~x / x | 0 for integer truncation.
Example:
// reports: unicorn/prefer-math-trunc (error)
const i = ~~3.7;unicorn/prefer-modern-dom-apis
Prefer before / after / replaceWith over insertBefore / replaceChild / insertAdjacentText.
Example:
const parent = document.createElement("div");
const ref = document.createElement("span");
const node = document.createElement("strong");
// reports: unicorn/prefer-modern-dom-apis (error)
parent.insertBefore(node, ref);unicorn/prefer-modern-math-apis
Prefer Math.log10 / Math.hypot / Math.log2 / Math.cbrt over their legacy approximations.
Example:
const x = 10;
// reports: unicorn/prefer-modern-math-apis (error)
const l = Math.log(x) * Math.LOG10E;unicorn/prefer-module
Prefer ES modules (import / export) over CommonJS (require / module.exports / __dirname / __filename).
Example:
// reports: unicorn/prefer-module (error)
require("path");unicorn/prefer-native-coercion-functions
Prefer the bare String / Number / Boolean / BigInt functions over x => String(x) arrow wrappers.
Example:
// reports: unicorn/prefer-native-coercion-functions (error)
const xs = ["1", "2"].map((x) => Number(x));unicorn/prefer-negative-index
Prefer negative-index lookups (arr.at(-1), arr.slice(-2)) over arr.length - 1 / arr.length - 2 arithmetic.
Example:
const a = [1, 2, 3];
// reports: unicorn/prefer-negative-index (error)
const tail = a.slice(a.length - 1);unicorn/prefer-node-protocol
Prefer node:fs / node:path / etc. over the bare Node builtin specifier.
Example:
// reports: unicorn/prefer-node-protocol (error)
import * as fs from "fs";unicorn/prefer-number-properties
Prefer the ES2015 Number static members over their global counterparts: Number.isNaN, Number.isFinite, Number.parseInt, Number.parseFloat, and, when enabled, Number.NaN, Number.POSITIVE_INFINITY, and Number.NEGATIVE_INFINITY. The namespaced forms coerce more predictably and are easier to discover. Only a reference to the real global is reported, so a locally shadowed parseInt or isNaN is left alone, and a parseInt(value) or parseInt(value, 10) call (already base 10) is not flagged.
Example:
// reports: unicorn/prefer-number-properties (error)
void isNaN(0);
const options = {
// reports: unicorn/prefer-number-properties (error)
normalize: parseFloat,
// reports: unicorn/prefer-number-properties (error)
parseInt,
};NaN and Infinity are unchecked by default. Set checkNaN: true to flag NaN, and checkInfinity: true to flag Infinity (a negated -Infinity fixes to Number.NEGATIVE_INFINITY):
// lint.config.json rule entry
"unicorn/prefer-number-properties": ["error", { "checkInfinity": true, "checkNaN": true }]The pure aliases (parseInt, parseFloat, NaN, Infinity) autofix directly. isNaN and isFinite autofix only when their sole argument is a number, since Number.isNaN and Number.isFinite skip the coercion the global forms perform; otherwise the rewrite is offered as a suggestion.
unicorn/prefer-object-from-entries
Prefer Object.fromEntries over reduce-into-object patterns.
Example:
const entries: Array<[string, number]> = [["a", 1]];
// reports: unicorn/prefer-object-from-entries (error)
const obj = entries.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});unicorn/prefer-optional-catch-binding
Prefer catch { ... } over catch (binding) { ... } when the caught error is never referenced. The binding is resolved through the type checker, so any unused name reports and a name that only appears in a comment or string literal still counts as unused.
Example:
try {
throw new Error("x");
// reports: unicorn/prefer-optional-catch-binding (error)
} catch (e) {
void 0;
}unicorn/prefer-prototype-methods
Prefer borrowing prototype methods (Array.prototype.slice.call) over [].slice.call empty-instance lookups.
Example:
// reports: unicorn/prefer-prototype-methods (error)
const slice = [].slice;unicorn/prefer-query-selector
Prefer Document#querySelector over getElementById, getElementsByClassName, and getElementsByTagName.
Example:
const doc = document;
// reports: unicorn/prefer-query-selector (error)
doc.getElementById("main");unicorn/prefer-reflect-apply
Prefer Reflect.apply(fn, thisArg, args) over Function.prototype.apply.call(fn, thisArg, args).
Example:
function f(a: number, b: number) {
return a + b;
}
// reports: unicorn/prefer-reflect-apply (error)
const r = Function.prototype.apply.call(f, null, [1, 2]);unicorn/prefer-regexp-test
Prefer RegExp#test over String#match / RegExp#exec when only a boolean is needed.
Example:
// reports: unicorn/prefer-regexp-test (error)
if ("abc".match(/a/)) {
void 0;
}unicorn/prefer-response-static-json
Prefer Response.json(value) over new Response( JSON.stringify(value), { headers: {"content-type": "application/json"} }).
Example:
// reports: unicorn/prefer-response-static-json (error)
const r = new Response(JSON.stringify({ ok: true }));unicorn/prefer-set-has
Prefer Set#has over Array#includes for repeated membership lookups against a constant collection.
Example:
const x = 2;
// reports: unicorn/prefer-set-has (error)
const found = [1, 2, 3].includes(x);unicorn/prefer-set-size
Prefer Set#size over [...set].length and Array.from(set).length.
Example:
const s = new Set([1, 2, 3]);
// reports: unicorn/prefer-set-size (error)
const n = [...s].length;unicorn/prefer-simple-condition-first
Prefer structurally simple conditions before complex conditions in boolean && / || chains. A simple condition is an identifier, a negated simple condition, or a strict comparison whose operands are identifiers, typeof identifiers, or literals. Value-producing logical expressions are not reported.
The fixer uses a stable partition, retaining the relative order of all simple conditions and of all complex conditions. It fixes only when every crossed complex condition is safe to move and no comment or TypeScript wrapper owns the affected logical syntax; otherwise the rule reports a diagnostic and leaves short-circuit behavior for manual review.
This rule has no options.
Illustrative shape:
function isAllowed(user: { role: string }) {
return user.role === "admin";
}
const user = { role: "admin" };
const featureEnabled = true;
// reports: unicorn/prefer-simple-condition-first (error)
if (isAllowed(user) && featureEnabled) {
console.log("enabled");
}
// fixed form
if (featureEnabled && isAllowed(user)) {
console.log("enabled");
}unicorn/prefer-single-call
Prefer a single push / unshift / classList.add / addEventListener with multiple arguments over consecutive single-argument calls.
Example:
const xs: number[] = [];
xs.push(1);
// reports: unicorn/prefer-single-call (error)
xs.push(2);unicorn/prefer-spread
Prefer spread ([...arr], [...str]) over Array.from, Array.prototype.slice.call, concat([]), and split('').
Example:
const a = [1, 2, 3];
// reports: unicorn/prefer-spread (error)
const b = Array.from(a);unicorn/prefer-string-raw
Prefer String.raw for path literals and other strings that would otherwise need backslash escapes.
The rule only reports when a String.raw template would reproduce the value exactly, so a literal is left alone when it carries any escape other than \\ ("\\d\t" would turn its tab into the two characters \t), when its value ends with a backslash (a raw template cannot end in one), when it contains a backtick or ${ (the template would close early or interpolate), or when a line continuation spreads it over two lines. A no-substitution template is reported under the same value-preserving condition, except that its newlines are already literal, so a multi-line template stays reportable; the quasi of a tagged template — including String.raw`…` itself — is never reported. The report carries no autofix.
Example:
// reports: unicorn/prefer-string-raw (error)
const p = "C:\\Users\\me";
// not reported: the tab escape would not survive String.raw
const q = "C:\\Users\tme";unicorn/prefer-string-replace-all
Prefer String#replaceAll(literal, replacement) over replace(/literal/g, replacement).
Example:
// reports: unicorn/prefer-string-replace-all (error)
const out = "abc".replace(/a/g, "x");unicorn/prefer-string-slice
Prefer String#slice over the deprecated substr / substring.
Example:
// reports: unicorn/prefer-string-slice (error)
const s = "hello".substr(0, 3);unicorn/prefer-string-starts-ends-with
Prefer String#startsWith / String#endsWith over equivalent RegExp#test and slice-then-compare idioms.
Example:
const s = "https://example.com";
// reports: unicorn/prefer-string-starts-ends-with (error)
const b = s.slice(0, 4) === "http";unicorn/prefer-string-trim-start-end
Prefer String#trimStart / String#trimEnd over the deprecated trimLeft / trimRight.
Example:
// reports: unicorn/prefer-string-trim-start-end (error)
const s = " hi ".trimLeft();unicorn/prefer-structured-clone
Prefer structuredClone(x) over JSON.parse(JSON.stringify(x)) for deep cloning.
Example:
const original = { a: 1 };
// reports: unicorn/prefer-structured-clone (error)
const clone = JSON.parse(JSON.stringify(original));unicorn/prefer-switch
Prefer switch over chains of three or more else if clauses comparing the same discriminant.
Example:
const k = "a";
// reports: unicorn/prefer-switch (error)
if (k === "a") {
void 0;
} else if (k === "b") {
void 0;
} else if (k === "c") {
void 0;
}unicorn/prefer-ternary
Prefer a ternary over if / else whose two branches differ only in the right-hand side of a common assignment, return, or throw.
Example:
const cond = true;
function f(): number {
// reports: unicorn/prefer-ternary (error)
if (cond) {
return 1;
} else {
return 2;
}
}unicorn/prefer-top-level-await
Prefer top-level await over .then / IIFE wrappers in ES modules.
Example:
async function load(): Promise<string> {
return "ready";
}
// reports: unicorn/prefer-top-level-await (error)
load().then((value) => console.log(value));unicorn/prefer-type-error
Require throwing TypeError (not a bare Error) when the surrounding if is a runtime type check.
Example:
function f(x: unknown) {
if (typeof x !== "number") {
// reports: unicorn/prefer-type-error (error)
throw new Error("must be number");
}
return x;
}unicorn/prevent-abbreviations
Apply the complete canonical replacement table to lexical bindings and their references, compound and cased names, and physical filenames.
The established unicorn/prevent-abbreviations ID is retained for configuration compatibility. Its behavior follows the final upstream version before eslint-plugin-unicorn renamed the rule to name-replacements in June 2026.
A binding is diagnosed once at its declaration. One collision-free replacement is autofixed across every reference, while ambiguous replacements are editor suggestions. Bindings declared with a named export modifier, plus ambient, cross-file-merged, JSX tag, .vue source, parameter-property, and attached-JSDoc @param bindings, remain diagnostic-only because a source-only rename cannot safely preserve their external names or references. A local binding re-exported through an export list remains fixable because the fixer preserves the external spelling (export { err } becomes export { error as err }). Default-export local names can likewise change without changing the external default name. The conservative .vue gate protects template references that are outside TypeScript’s source-file AST.
The option object supports replacements, extendDefaultReplacements, allowList, extendDefaultAllowList, ignore, checkVariables, checkProperties, checkFilenames, checkShorthandProperties, checkDefaultAndNamespaceImports, and checkShorthandImports. Import controls accept true, false, or "internal". The ignore option accepts regular-expression strings.
Example:
// reports once and fixes both occurrences to `button`
const btn = document.querySelector("button");
btn?.focus();export default {
rules: {
"unicorn/prevent-abbreviations": [
"error",
{
checkProperties: true,
replacements: {
cmd: { command: true },
ref: false,
},
},
],
},
};unicorn/relative-url-style
Enforce a single style (always leading ./ vs. never) for relative URLs passed to new URL.
Example:
const base = "https://example.com";
const u = new URL(
// reports: unicorn/relative-url-style (error)
"./dashboard",
base,
);unicorn/require-array-join-separator
Require an explicit separator argument to Array#join instead of relying on the default ",".
Example:
// reports: unicorn/require-array-join-separator (error)
const s = [1, 2, 3].join();unicorn/require-module-attributes
Require non-empty with / assert options on import / export statements that use them at all.
Example:
// reports: unicorn/require-module-attributes (error)
import data from "./data.json";unicorn/require-module-specifiers
Require a non-empty specifier list on every import / export statement.
Example:
// reports: unicorn/require-module-specifiers (error)
import "./side-effect.js";unicorn/require-number-to-fixed-digits-argument
Require an explicit digits argument to Number#toFixed.
Example:
// reports: unicorn/require-number-to-fixed-digits-argument (error)
const s = (1.234).toFixed();unicorn/require-post-message-target-origin
Require an explicit targetOrigin argument to window.postMessage.
Example:
const win = window;
// reports: unicorn/require-post-message-target-origin (error)
win.postMessage({ kind: "ping" });unicorn/string-content
Rewrite configured patterns inside string literals and template quasis (e.g., curly quotes for straight ones, ... into a real ellipsis).
The rule has no default patterns: a bare severity reports nothing. The options object maps regular-expression sources to replacements under patterns; the first configured pattern that matches a string wins, and every occurrence is replaced. A replacement is either the suggestion string or an object with suggest (required), fix (default true; false reports the rewrite as an opt-in editor suggestion), caseSensitive (default true), and message (custom diagnostic text with {{match}} / {{suggest}} placeholders).
String literals match on their cooked value and are re-quoted with escapes preserved; JSX attribute strings encode the delimiter quote as an HTML entity because they cannot use backslash escapes. Template quasis match on their raw text, keep substitutions untouched, and re-escape backticks and ${ introduced by a replacement; quasis under the gql / html / sql / svg tags and styled.* member tags are exempt. The selectors list replaces the default Literal / TemplateElement targets with AST selectors.
Illustrative shape:
// With `patterns: { unicorn: "🦄" }` configured:
// reports: unicorn/string-content (error)
const label = "unicorn";unicorn/switch-case-braces
Enforce a consistent presence/absence of {} braces around case clauses inside switch.
Example:
const k = "a";
switch (k) {
// reports: unicorn/switch-case-braces (error)
case "a":
void 0;
break;
}unicorn/switch-case-break-position
Require a terminating break, continue, return, or throw to sit inside a case clause’s sole block instead of immediately after it. break and continue are automatically moved when comments and layout make that safe; return and throw remain diagnostic-only because moving their expressions can change block-scoped binding resolution.
Illustrative shape:
const state = "idle";
function reset(): void {}
switch (state) {
case "idle": {
reset();
}
break;
}unicorn/template-indent
Normalize whitespace-insensitive multiline template bodies relative to the source line containing the opening backtick. Substitutions, nested expressions, raw escapes, blank lines, and the source line-ending style are preserved.
By default, the rule checks the outdent, dedent, gql, sql, html, and styled tags; template arguments passed directly to dedent or stripIndent; templates preceded by /* HTML */ or /* indent */; and Jest inline snapshots. The options object can replace the tags, functions, comments, and selectors lists. indent accepts either a positive number of spaces or an exact non-empty whitespace string such as "\t".
Illustrative shape:
function sql(strings: TemplateStringsArray): string {
return strings.join("");
}
const query = sql`
SELECT *
FROM users
WHERE active = true
`;unicorn/text-encoding-identifier-case
Enforce a canonical case for text-encoding identifiers — the dash-less "utf8" by default (so "UTF-8", "utf-8", and "Utf8" all report toward "utf8").
Only utf-8 / utf8 and ascii are recognized; every other label ("latin1", "UTF-16LE", …) passes through untouched. ascii is always the lowercase form. The dashed WHATWG spelling "utf-8" is enforced instead of the default in the contexts that echo the label back verbatim: the first argument of new TextDecoder(...), a JSX <meta charset> attribute, and a JSX <form accept-charset> attribute — or everywhere when the withDash: true option is set.
Only the encoding argument of fs.readFile() / fs.readFileSync() is autofixed; every other position reports an opt-in editor suggestion instead.
Example:
// reports: unicorn/text-encoding-identifier-case (error) — prefer "utf8"
const enc = "utf-8";
// reports: unicorn/text-encoding-identifier-case (error) — prefer "utf-8" here
const decoder = new TextDecoder("utf8");unicorn/throw-new-error
Require throw new Error(...) over throw Error(...).
A thrown call is reported when its callee names an error constructor: a plain identifier, or a non-computed property access whose property name matches ^(?:[A-Z][\da-z]*)*Error$ (capitalized words closed by Error). That covers the built-ins (TypeError) and user-defined classes alike (ValidationError, ns.HttpError), while getError(), fooError(), and computed access (ns["FooError"]()) stay silent. An optional-chained callee (Error?.(), ns?.FooError()) is never reported, because new cannot be applied to an optional chain.
The autofix inserts new in front of the call. It parenthesizes a callee whose object chain still exposes a call, because a new expression’s callee ends at the first argument list: throw getGlobalThis().Error() becomes throw new (getGlobalThis().Error)().
Example:
// reports: unicorn/throw-new-error (error)
throw Error("oops");
// reports: unicorn/throw-new-error (error)
throw ValidationError("bad");
// reports: unicorn/throw-new-error (error)
throw ns.HttpError(404);