β¬ οΈ Back to Table of Contents
π no-magic-numbers¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 11 |
| π¦ Imports | 8 |
| π Variables & Constants | 2 |
| π Type Aliases | 2 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/no-magic-numbers.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'no-magic-numbers' |
meta.type |
'suggestion' |
meta.docs.description |
'Disallow magic numbers' |
meta.docs.extendsBaseRule |
true |
meta.docs.frozen |
true |
meta.messages |
baseRule.meta.messages |
meta.schema |
[schema] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
JSONSchema4 |
@typescript-eslint/utils/json-schema |
AST_NODE_TYPES |
@typescript-eslint/utils |
InferMessageIdsTypeFromRule |
../util |
InferOptionsTypeFromRule |
../util |
createRule |
../util |
deepMerge |
../util |
getESLintCoreRule |
../util/getESLintCoreRule |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
schema |
JSONSchema4 |
const | deepMerge( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument ... |
β |
defaultOptions |
Options |
const | [ { detectObjects: false, enforceConst: false, ignore: [], ignoreArrayIndexes... |
β |
Functions¶
create(context: any, [options]: any): { Literal(node: any): void; }¶
Parameters:
contextany[options]any
Returns: { Literal(node: any): void; }
Calls:
baseRule.create(options.ignore ?? []).mapignored.hasnormalizeLiteralValueisParentTSEnumDeclarationisTSNumericLiteralTypeisAncestorTSIndexedAccessTypeisParentTSReadonlyPropertyDefinitioncontext.reportrules.Literal
Internal Comments:
// If itβs not a numeric literal weβre not interested
// This will be `true` if weβre configured to ignore this case (eg. itβs (x2)
// an enum and `ignoreEnums` is `true`). It will be `false` if weβre not (x2)
// configured to ignore this case. It will remain `undefined` if this is (x2)
// not one of our exception cases, and weβll fall back to the base rule. (x2)
// Check if the node is ignored
// If weβve hit a case where the ignore option is true we can return now
// If the ignore option is *not* set we can report it now
// the base rule only shows the operator for negative numbers (x4)
// https://github.com/eslint/eslint/blob/9dfc8501fb1956c90dc11e6377b4cb38a6bea65d/lib/rules/no-magic-numbers.js#L126 (x4)
// Let the base rule deal with the rest (x4)
Code
create(context, [options]) {
const rules = baseRule.create(context);
const ignored = new Set((options.ignore ?? []).map(normalizeIgnoreValue));
return {
Literal(node): void {
// If itβs not a numeric literal weβre not interested
if (typeof node.value !== 'number' && typeof node.value !== 'bigint') {
return;
}
// This will be `true` if weβre configured to ignore this case (eg. itβs
// an enum and `ignoreEnums` is `true`). It will be `false` if weβre not
// configured to ignore this case. It will remain `undefined` if this is
// not one of our exception cases, and weβll fall back to the base rule.
let isAllowed: boolean | undefined;
// Check if the node is ignored
if (ignored.has(normalizeLiteralValue(node, node.value))) {
isAllowed = true;
}
// Check if the node is a TypeScript enum declaration
else if (isParentTSEnumDeclaration(node)) {
isAllowed = options.ignoreEnums === true;
}
// Check TypeScript specific nodes for Numeric Literal
else if (isTSNumericLiteralType(node)) {
isAllowed = options.ignoreNumericLiteralTypes === true;
}
// Check if the node is a type index
else if (isAncestorTSIndexedAccessType(node)) {
isAllowed = options.ignoreTypeIndexes === true;
}
// Check if the node is a readonly class property
else if (isParentTSReadonlyPropertyDefinition(node)) {
isAllowed = options.ignoreReadonlyClassProperties === true;
}
// If weβve hit a case where the ignore option is true we can return now
if (isAllowed === true) {
return;
}
// If the ignore option is *not* set we can report it now
if (isAllowed === false) {
let fullNumberNode: TSESTree.Literal | TSESTree.UnaryExpression =
node;
let raw = node.raw;
if (
node.parent.type === AST_NODE_TYPES.UnaryExpression &&
// the base rule only shows the operator for negative numbers
// https://github.com/eslint/eslint/blob/9dfc8501fb1956c90dc11e6377b4cb38a6bea65d/lib/rules/no-magic-numbers.js#L126
node.parent.operator === '-'
) {
fullNumberNode = node.parent;
raw = `${node.parent.operator}${node.raw}`;
}
context.report({
node: fullNumberNode,
messageId: 'noMagic',
data: { raw },
});
return;
}
// Let the base rule deal with the rest
rules.Literal(node);
},
};
}
normalizeIgnoreValue(value: bigint | number | string): bigint | number¶
Convert the value to bigint if it's a string. Otherwise, return the value as-is.
Parameters:
valueany: The value to normalize.
Returns: undefined
The normalized value.
Raw JSDoc
Calls:
BigIntvalue.slice
Code
normalizeLiteralValue(node: TSESTree.BigIntLiteral | TSESTree.Numbeβ¦, value: bigint | number): bigint | number¶
Converts the node to its numeric value, handling prefixed numbers (-1 / +1)
Parameters:
nodeany: the node to normalize.valueany: the node's value.
Raw JSDoc
Calls:
['-', '+'].includes
Code
function normalizeLiteralValue(
node: TSESTree.BigIntLiteral | TSESTree.NumberLiteral,
value: bigint | number,
): bigint | number {
if (
node.parent.type === AST_NODE_TYPES.UnaryExpression &&
['-', '+'].includes(node.parent.operator) &&
node.parent.operator === '-'
) {
return -value;
}
return value;
}
getLiteralParent(node: TSESTree.Literal): TSESTree.Node | undefined¶
Gets the true parent of the literal, handling prefixed numbers (-1 / +1)
Calls:
['-', '+'].includes
Code
isGrandparentTSTypeAliasDeclaration(node: TSESTree.Node): boolean¶
Checks if the node grandparent is a Typescript type alias declaration
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node grandparent is a Typescript type alias declaration
Tags: @private
Raw JSDoc
Code
isGrandparentTSUnionType(node: TSESTree.Node): boolean¶
Checks if the node grandparent is a Typescript union type and its parent is a type alias declaration
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node grandparent is a Typescript union type and its parent is a type alias declaration
Tags: @private
Raw JSDoc
Calls:
isGrandparentTSTypeAliasDeclaration
Code
isParentTSEnumDeclaration(node: TSESTree.Literal): boolean¶
Checks if the node parent is a Typescript enum member
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node parent is a Typescript enum member
Tags: @private
Raw JSDoc
Calls:
getLiteralParent
Code
isParentTSLiteralType(node: TSESTree.Node): boolean¶
Checks if the node parent is a Typescript literal type
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node parent is a Typescript literal type
Tags: @private
Raw JSDoc
Code
isTSNumericLiteralType(node: TSESTree.Node): boolean¶
Checks if the node is a valid TypeScript numeric literal type.
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node is a TypeScript numeric literal type.
Tags: @private
Raw JSDoc
Calls:
isParentTSLiteralTypeisGrandparentTSTypeAliasDeclarationisGrandparentTSUnionType
Internal Comments:
// For negative numbers, use the parent node
// If the parent node is not a TSLiteralType, early return
// If the grandparent is a TSTypeAliasDeclaration, ignore
// If the grandparent is a TSUnionType and it's parent is a TSTypeAliasDeclaration, ignore
Code
function isTSNumericLiteralType(node: TSESTree.Node): boolean {
// For negative numbers, use the parent node
if (
node.parent?.type === AST_NODE_TYPES.UnaryExpression &&
node.parent.operator === '-'
) {
node = node.parent;
}
// If the parent node is not a TSLiteralType, early return
if (!isParentTSLiteralType(node)) {
return false;
}
// If the grandparent is a TSTypeAliasDeclaration, ignore
if (isGrandparentTSTypeAliasDeclaration(node)) {
return true;
}
// If the grandparent is a TSUnionType and it's parent is a TSTypeAliasDeclaration, ignore
if (isGrandparentTSUnionType(node)) {
return true;
}
return false;
}
isParentTSReadonlyPropertyDefinition(node: TSESTree.Literal): boolean¶
Checks if the node parent is a readonly class property
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node parent is a readonly class property
Tags: @private
Raw JSDoc
Calls:
getLiteralParent
Code
isAncestorTSIndexedAccessType(node: TSESTree.Literal): boolean¶
Checks if the node is part of a type indexed access (eg. Foo[4])
Parameters:
nodeany: the node to be validated.
Returns: undefined
true if the node is part of an indexed access
Tags: @private
Raw JSDoc
Calls:
getLiteralParent
Internal Comments:
// Handle unary expressions (eg. -4) (x2)
// Go up another level while weβre part of a type union (eg. 1 | 2) or
// intersection (eg. 1 & 2)
Code
function isAncestorTSIndexedAccessType(node: TSESTree.Literal): boolean {
// Handle unary expressions (eg. -4)
let ancestor = getLiteralParent(node);
// Go up another level while weβre part of a type union (eg. 1 | 2) or
// intersection (eg. 1 & 2)
while (
ancestor?.parent?.type === AST_NODE_TYPES.TSUnionType ||
ancestor?.parent?.type === AST_NODE_TYPES.TSIntersectionType
) {
ancestor = ancestor.parent;
}
return ancestor?.parent?.type === AST_NODE_TYPES.TSIndexedAccessType;
}
Type Aliases¶
Options¶
MessageIds¶
Generated by Syntax Scribe