no-magic-numbers

Require numbers to be given a name instead of being used directly

A bare number in the middle of an expression doesn't tell you what it stands for. If the same number is used in several places, you have to find and change each one. A named constant explains the number and keeps it in one place.

The rule doesn't report the number a variable is declared with, the values in an object literal, a number assigned to a property, the second argument of parseInt(), or numbers in JSX. It reports everything else, including 0 and 1.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"no-magic-numbers" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"no-magic-numbers" = ["error", {
  ignore = [], # list of numbers or strings
  ignoreArrayIndexes = false,
  ignoreDefaultValues = false,
  ignoreClassFieldInitialValues = false,
  enforceConst = false,
  detectObjects = false,
  ignoreEnums = false,
  ignoreNumericLiteralTypes = false,
  ignoreReadonlyClassProperties = false,
  ignoreTypeIndexes = false,
}]

Examples#

example.js2 problems
function priceWithTax(price) {
  return price * 1.2;
}

setInterval(refresh, 60000);
example.jsNo problems
const TAX_RATE = 1.2;
const ONE_MINUTE = 60000;

function priceWithTax(price) {
  return price * TAX_RATE;
}

setInterval(refresh, ONE_MINUTE);
example.jsxNo problems
const server = { port: 8080 };
server.timeout = 5000;
const quantity = parseInt(input.value, 10);
const grid = <Grid columns={3} />;

Options#

OptionDefaultWhat it does
ignore[]Numbers that are never reported. Write a bigint as a string: "100n".
ignoreArrayIndexesfalseAllow a number as an index: items[0].
ignoreDefaultValuesfalseAllow a number as a default value for a parameter or in destructuring.
ignoreClassFieldInitialValuesfalseAllow a number as the initial value of a class field.
enforceConstfalseReport a variable that's declared with a number and isn't a const.
detectObjectsfalseAlso report numbers in object literals and numbers assigned to a property.
ignoreEnumsfalseTypeScript: allow numbers in enum members.
ignoreNumericLiteralTypesfalseTypeScript: allow numbers in a type alias such as type Dice = 1 | 2.
ignoreReadonlyClassPropertiesfalseTypeScript: allow numbers in readonly class properties.
ignoreTypeIndexesfalseTypeScript: allow a number as the index of a type: Row[0].
example.jswith { "ignore": [0, 1] }No problems
const isLast = index === items.length - 1;
const isEmpty = items.length === 0;

Each of these lines is reported by default:

example.js3 problems
const first = items[0];
function retry(times = 3) {}
class Pool { size = 10; }
example.jswith { "ignoreArrayIndexes": true, "ignoreDefaultValues": true, "ignoreClassFieldInitialValues": true }No problems
const first = items[0];
function retry(times = 3) {}
class Pool { size = 10; }
example.jswith { "enforceConst": true }1 problem
let timeout = 5000;
example.jswith { "detectObjects": true }2 problems
const server = { port: 8080 };
server.timeout = 5000;

The same goes for TypeScript. Each of these lines is reported by default:

example.ts5 problems
enum Level { Debug = 10 }
type Dice = 1 | 2;
class Pool { readonly size = 10; }
type First = Row[0];
example.tswith { "ignoreEnums": true, "ignoreNumericLiteralTypes": true, "ignoreReadonlyClassProperties": true, "ignoreTypeIndexes": true }No problems
enum Level { Debug = 10 }
type Dice = 1 | 2;
class Pool { readonly size = 10; }
type First = Row[0];

When not to use it#

Code that's full of numbers with an obvious meaning, such as math, geometry or test data, gets a report on nearly every line.