unicorn/prefer-at

Require .at() to read an element counted from the end of an array or string

fixable

.at(-1) reads the last element. Without it, you have to name the array twice, as in items[items.length - 1], or copy part of it with .slice(-1)[0].

Taking one character with .substring(index, index + 1) is reported too.

--fix rewrites these to .at(), except .substring(), which treats an index outside the string differently. --fix-suggestions rewrites that one.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"unicorn/prefer-at" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"unicorn/prefer-at" = ["error", {
  checkAllIndexAccess = false,
  getLastElementFunctions = [], # list of strings
}]

Examples#

example.js7 problems
const last = items[items.length - 1];
const secondToLast = items.slice(-2)[0];
const tail = items.slice(-1).pop();
const newest = _.last(items);
const end = name.charAt(name.length - 1);
const letter = name.substring(index, index + 1);
example.jsNo problems
const last = items.at(-1);
const secondToLast = items.at(-2);
const end = name.at(-1);
const letter = name.at(index);
const first = items[0];

.at() only reads, so writing to an element isn't reported:

example.jsNo problems
items[items.length - 1] = value;

Options#

OptionDefaultWhat it does
checkAllIndexAccessfalseAlso report an index counted from the start, such as items[0] and name.charAt(2).
getLastElementFunctions[]Other objects with a last() function to report, besides _, lodash and underscore.
example.jswith { "checkAllIndexAccess": true }2 problems
const first = items[0];
const third = name.charAt(2);
example.jswith { "getLastElementFunctions": ["utils"] }1 problem
const newest = utils.last(items);

When not to use it#

.at() returns undefined past the end of a string, where .charAt() and .substring() return "". Check code that relies on the empty string before you change it.