From f39cc85f9da265af3f38ef47de1ae9f0201a9172 Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Mon, 25 Mar 2019 17:11:38 +1100 Subject: [PATCH 1/4] feat(eslint-plugin): add no-magic-numbers rule --- packages/eslint-plugin/README.md | 1 + .../docs/rules/no-magic-numbers.md | 159 ++++++++++++++++++ .../src/rules/no-magic-numbers.ts | 149 ++++++++++++++++ .../tests/rules/no-magic-numbers.test.ts | 134 +++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 22 +++ 5 files changed, 465 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-magic-numbers.md create mode 100644 packages/eslint-plugin/src/rules/no-magic-numbers.ts create mode 100644 packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 6d433a5eef5..1e4c27bbea8 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -131,6 +131,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces (`no-unnecessary-class` from TSLint) | | | | | [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop (`no-for-in-array` from TSLint) | | | :thought_balloon: | | [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean. (`no-inferrable-types` from TSLint) | :heavy_check_mark: | :wrench: | | +| [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallows magic numbers. | :heavy_check_mark: | | | [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor`. (`no-misused-new` from TSLint) | :heavy_check_mark: | | | | [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces (`no-namespace` from TSLint) | :heavy_check_mark: | | | | [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator (`no-non-null-assertion` from TSLint) | :heavy_check_mark: | | | diff --git a/packages/eslint-plugin/docs/rules/no-magic-numbers.md b/packages/eslint-plugin/docs/rules/no-magic-numbers.md new file mode 100644 index 00000000000..2e6fbfb7cfd --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-magic-numbers.md @@ -0,0 +1,159 @@ +# Disallow Magic Numbers (no-magic-numbers) + +'Magic numbers' are numbers that occur multiple time in code without an explicit meaning. +They should preferably be replaced by named constants. + +```js +var now = Date.now(), + inOneHour = now + 60 * 60 * 1000; +``` + +## Rule Details + +The `no-magic-numbers` rule aims to make code more readable and refactoring easier by ensuring that special numbers +are declared as constants to make their meaning explicit. + +**_This rule was taken from the ESLint core rule `no-magic-numbers`._** +**_Available options and test cases may vary depending on the version of ESLint installed in the system._** + +Examples of **incorrect** code for this rule: + +```js +/*eslint no-magic-numbers: "error"*/ + +var dutyFreePrice = 100, + finalPrice = dutyFreePrice + dutyFreePrice * 0.25; +``` + +```js +/*eslint no-magic-numbers: "error"*/ + +var data = ['foo', 'bar', 'baz']; + +var dataLast = data[2]; +``` + +```js +/*eslint no-magic-numbers: "error"*/ + +var SECONDS; + +SECONDS = 60; +``` + +Examples of **correct** code for this rule: + +```js +/*eslint no-magic-numbers: "error"*/ + +var TAX = 0.25; + +var dutyFreePrice = 100, + finalPrice = dutyFreePrice + dutyFreePrice * TAX; +``` + +## Options + +```cjson +{ + // note you must disable the base rule as it can report incorrect errors + "no-magic-numbers": "off", + "@typescript-eslint/no-magic-numbers": ["error", { "ignoreNumericLiteralTypes": true }] +} +``` + +### ignore + +An array of numbers to ignore. It's set to `[]` by default. +If provided, it must be an `Array`. + +Examples of **correct** code for the sample `{ "ignore": [1] }` option: + +```js +/*eslint no-magic-numbers: ["error", { "ignore": [1] }]*/ + +var data = ['foo', 'bar', 'baz']; +var dataLast = data.length && data[data.length - 1]; +``` + +### ignoreArrayIndexes + +A boolean to specify if numbers used as array indexes are considered okay. `false` by default. + +Examples of **correct** code for the `{ "ignoreArrayIndexes": true }` option: + +```js +/*eslint no-magic-numbers: ["error", { "ignoreArrayIndexes": true }]*/ + +var data = ['foo', 'bar', 'baz']; +var dataLast = data[2]; +``` + +### enforceConst + +A boolean to specify if we should check for the const keyword in variable declaration of numbers. `false` by default. + +Examples of **incorrect** code for the `{ "enforceConst": true }` option: + +```js +/*eslint no-magic-numbers: ["error", { "enforceConst": true }]*/ + +var TAX = 0.25; + +var dutyFreePrice = 100, + finalPrice = dutyFreePrice + dutyFreePrice * TAX; +``` + +### detectObjects + +A boolean to specify if we should detect numbers when setting object properties for example. `false` by default. + +Examples of **incorrect** code for the `{ "detectObjects": true }` option: + +```js +/*eslint no-magic-numbers: ["error", { "detectObjects": true }]*/ + +var magic = { + tax: 0.25, +}; + +var dutyFreePrice = 100, + finalPrice = dutyFreePrice + dutyFreePrice * magic.tax; +``` + +Examples of **correct** code for the `{ "detectObjects": true }` option: + +```js +/*eslint no-magic-numbers: ["error", { "detectObjects": true }]*/ + +var TAX = 0.25; + +var magic = { + tax: TAX, +}; + +var dutyFreePrice = 100, + finalPrice = dutyFreePrice + dutyFreePrice * magic.tax; +``` + +### ignoreNumericLiteralTypes + +A boolean to specify if numbers used in Typescript numeric literal types are considered okay. `false` by default. + +Examples of **incorrect** code for the `{ "ignoreNumericLiteralTypes": false }` option: + +```ts +/*eslint no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": false }]*/ + +type SmallPrimes = 2 | 3 | 5 | 7 | 11; +``` + +Examples of **correct** code for the `{ "ignoreNumericLiteralTypes": true }` option: + +```ts +/*eslint no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": true }]*/ + +type SmallPrimes = 2 | 3 | 5 | 7 | 11; +``` + +Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-magic-numbers.md) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts new file mode 100644 index 00000000000..9421e39ba21 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -0,0 +1,149 @@ +/** + * @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js) + * @author Scott O'Hara + */ + +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import baseRule from 'eslint/lib/rules/no-magic-numbers'; +import * as util from '../util'; +import { JSONSchema4 } from 'json-schema'; + +type Options = util.InferOptionsTypeFromRule; +type MessageIds = util.InferMessageIdsTypeFromRule; + +// Original schema properties from the base rule +const { properties } = (baseRule.meta.schema as JSONSchema4[])[0]; + +// Extend base schema with additional property to ignore TS numeric literal types +if (properties) { + properties.ignoreNumericLiteralTypes = { + type: 'boolean', + }; +} + +export default util.createRule({ + name: 'no-magic-numbers', + meta: { + type: 'suggestion', + docs: { + description: 'Disallow magic numbers', + category: 'Best Practices', + recommended: false, + }, + schema: baseRule.meta.schema, + messages: baseRule.meta.messages, + }, + defaultOptions: [ + { + ignore: [], + ignoreArrayIndexes: false, + enforceConst: false, + detectObjects: false, + ignoreNumericLiteralTypes: false, + }, + ], + create(context, [options]) { + const rules = baseRule.create(context); + + /** + * Returns whether the node is number literal + * @param node the node literal being evaluated + * @returns true if the node is a number literal + */ + function isNumber(node: TSESTree.Literal): boolean { + return typeof node.value === 'number'; + } + + /** + * Checks if the node grandparent is a Typescript type alias declaration + * @param node the node to be validated. + * @returns true if the node grandparent is a Typescript type alias declaration + * @private + */ + function isGrandparentTSTypeAliasDeclaration(node: TSESTree.Node): boolean { + return node.parent && node.parent.parent + ? AST_NODE_TYPES.TSTypeAliasDeclaration === node.parent.parent.type + : false; + } + + /** + * Checks if the node grandparent is a Typescript union type and its parent is a type alias declaration + * @param node the node to be validated. + * @returns true if the node grandparent is a Typescript untion type and its parent is a type alias declaration + * @private + */ + function isGrandparentTSUnionType(node: TSESTree.Node): boolean { + if ( + node.parent && + node.parent.parent && + AST_NODE_TYPES.TSUnionType === node.parent.parent.type + ) { + return isGrandparentTSTypeAliasDeclaration(node.parent); + } + + return false; + } + + /** + * Checks if the node parent is a Typescript literal type + * @param node the node to be validated. + * @returns true if the node parent is a Typescript literal type + * @private + */ + function isParentTSLiteralType(node: TSESTree.Node): boolean { + return node.parent + ? AST_NODE_TYPES.TSLiteralType === node.parent.type + : false; + } + + /** + * Checks if the node is a valid TypeScript numeric literal type. + * @param node the node to be validated. + * @returns true if the node is a TypeScript numeric literal type. + * @private + */ + function isTSNumericLiteralType(node: TSESTree.Node): boolean { + // For negative numbers, update the parent node + if ( + node.parent && + 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; + } + + return { + Literal(node) { + // Check TypeScript specific nodes + if ( + options.ignoreNumericLiteralTypes && + isNumber(node) && + isTSNumericLiteralType(node) + ) { + return; + } + + // Let the base rule deal with the rest + rules.Literal(node); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts new file mode 100644 index 00000000000..2b184ad76b2 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts @@ -0,0 +1,134 @@ +import rule from '../../src/rules/no-magic-numbers'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-magic-numbers', rule, { + valid: [ + { + code: 'const FOO = 10;', + options: [{ ignoreNumericLiteralTypes: true }], + }, + { + code: 'type Foo = "bar";', + }, + { + code: 'type Foo = true;', + }, + { + code: 'type Foo = 1;', + options: [{ ignoreNumericLiteralTypes: true }], + }, + { + code: 'type Foo = -1;', + options: [{ ignoreNumericLiteralTypes: true }], + }, + { + code: 'type Foo = 1 | 2 | 3;', + options: [{ ignoreNumericLiteralTypes: true }], + }, + { + code: 'type Foo = 1 | -1;', + options: [{ ignoreNumericLiteralTypes: true }], + }, + ], + + invalid: [ + { + code: 'type Foo = 1;', + options: [{ ignoreNumericLiteralTypes: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1', + }, + line: 1, + column: 12, + }, + ], + }, + { + code: 'type Foo = -1;', + options: [{ ignoreNumericLiteralTypes: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '-1', + }, + line: 1, + column: 12, + }, + ], + }, + { + code: 'type Foo = 1 | 2 | 3;', + options: [{ ignoreNumericLiteralTypes: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1', + }, + line: 1, + column: 12, + }, + { + messageId: 'noMagic', + data: { + raw: '2', + }, + line: 1, + column: 16, + }, + { + messageId: 'noMagic', + data: { + raw: '3', + }, + line: 1, + column: 20, + }, + ], + }, + { + code: 'type Foo = 1 | -1;', + options: [{ ignoreNumericLiteralTypes: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1', + }, + line: 1, + column: 12, + }, + { + messageId: 'noMagic', + data: { + raw: '-1', + }, + line: 1, + column: 16, + }, + ], + }, + { + code: 'interface Foo { bar: 1; }', + options: [{ ignoreNumericLiteralTypes: true }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1', + }, + line: 1, + column: 22, + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index b4094c05474..004c89359ad 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -174,6 +174,28 @@ declare module 'eslint/lib/rules/no-implicit-globals' { export = rule; } +declare module 'eslint/lib/rules/no-magic-numbers' { + import { TSESTree } from '@typescript-eslint/typescript-estree'; + import RuleModule from 'ts-eslint'; + + const rule: RuleModule< + 'noMagic', + [ + { + ignore?: string[]; + ignoreArrayIndexes?: boolean; + enforceConst?: boolean; + detectObjects?: boolean; + ignoreNumericLiteralTypes?: boolean; + } + ], + { + Literal(node: TSESTree.Literal): void; + } + >; + export = rule; +} + declare module 'eslint/lib/rules/no-redeclare' { import { TSESTree } from '@typescript-eslint/typescript-estree'; import RuleModule from 'ts-eslint'; From aca6d080439a2108ed64d31d6734c5323ecace4d Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Thu, 28 Mar 2019 08:50:41 +1100 Subject: [PATCH 2/4] feat(eslint-plugin): update docs and fix nits --- .../docs/rules/no-magic-numbers.md | 131 ++---------------- .../src/rules/no-magic-numbers.ts | 20 ++- 2 files changed, 17 insertions(+), 134 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-magic-numbers.md b/packages/eslint-plugin/docs/rules/no-magic-numbers.md index 2e6fbfb7cfd..2ff5aab519d 100644 --- a/packages/eslint-plugin/docs/rules/no-magic-numbers.md +++ b/packages/eslint-plugin/docs/rules/no-magic-numbers.md @@ -1,58 +1,15 @@ -# Disallow Magic Numbers (no-magic-numbers) +# Disallow Magic Numbers (@typescript-eslint/no-magic-numbers) -'Magic numbers' are numbers that occur multiple time in code without an explicit meaning. +'Magic numbers' are numbers that occur multiple times in code without an explicit meaning. They should preferably be replaced by named constants. -```js -var now = Date.now(), - inOneHour = now + 60 * 60 * 1000; -``` - ## Rule Details -The `no-magic-numbers` rule aims to make code more readable and refactoring easier by ensuring that special numbers -are declared as constants to make their meaning explicit. - -**_This rule was taken from the ESLint core rule `no-magic-numbers`._** -**_Available options and test cases may vary depending on the version of ESLint installed in the system._** - -Examples of **incorrect** code for this rule: - -```js -/*eslint no-magic-numbers: "error"*/ - -var dutyFreePrice = 100, - finalPrice = dutyFreePrice + dutyFreePrice * 0.25; -``` +The `@typescript-eslint/no-magic-numbers` rule extends the `no-magic-numbers` rule from ESLint core, and adds support for handling Typescript specific code that would otherwise trigger the rule. -```js -/*eslint no-magic-numbers: "error"*/ +See the [ESLint documentation](https://eslint.org/docs/rules/no-magic-numbers) for more details on the `no-magic-numbers` rule. -var data = ['foo', 'bar', 'baz']; - -var dataLast = data[2]; -``` - -```js -/*eslint no-magic-numbers: "error"*/ - -var SECONDS; - -SECONDS = 60; -``` - -Examples of **correct** code for this rule: - -```js -/*eslint no-magic-numbers: "error"*/ - -var TAX = 0.25; - -var dutyFreePrice = 100, - finalPrice = dutyFreePrice + dutyFreePrice * TAX; -``` - -## Options +## Rule Changes ```cjson { @@ -62,79 +19,7 @@ var dutyFreePrice = 100, } ``` -### ignore - -An array of numbers to ignore. It's set to `[]` by default. -If provided, it must be an `Array`. - -Examples of **correct** code for the sample `{ "ignore": [1] }` option: - -```js -/*eslint no-magic-numbers: ["error", { "ignore": [1] }]*/ - -var data = ['foo', 'bar', 'baz']; -var dataLast = data.length && data[data.length - 1]; -``` - -### ignoreArrayIndexes - -A boolean to specify if numbers used as array indexes are considered okay. `false` by default. - -Examples of **correct** code for the `{ "ignoreArrayIndexes": true }` option: - -```js -/*eslint no-magic-numbers: ["error", { "ignoreArrayIndexes": true }]*/ - -var data = ['foo', 'bar', 'baz']; -var dataLast = data[2]; -``` - -### enforceConst - -A boolean to specify if we should check for the const keyword in variable declaration of numbers. `false` by default. - -Examples of **incorrect** code for the `{ "enforceConst": true }` option: - -```js -/*eslint no-magic-numbers: ["error", { "enforceConst": true }]*/ - -var TAX = 0.25; - -var dutyFreePrice = 100, - finalPrice = dutyFreePrice + dutyFreePrice * TAX; -``` - -### detectObjects - -A boolean to specify if we should detect numbers when setting object properties for example. `false` by default. - -Examples of **incorrect** code for the `{ "detectObjects": true }` option: - -```js -/*eslint no-magic-numbers: ["error", { "detectObjects": true }]*/ - -var magic = { - tax: 0.25, -}; - -var dutyFreePrice = 100, - finalPrice = dutyFreePrice + dutyFreePrice * magic.tax; -``` - -Examples of **correct** code for the `{ "detectObjects": true }` option: - -```js -/*eslint no-magic-numbers: ["error", { "detectObjects": true }]*/ - -var TAX = 0.25; - -var magic = { - tax: TAX, -}; - -var dutyFreePrice = 100, - finalPrice = dutyFreePrice + dutyFreePrice * magic.tax; -``` +In addition to the options supported by the `no-magic-numbers` rule in ESLint core, the rule adds the following options: ### ignoreNumericLiteralTypes @@ -143,7 +28,7 @@ A boolean to specify if numbers used in Typescript numeric literal types are con Examples of **incorrect** code for the `{ "ignoreNumericLiteralTypes": false }` option: ```ts -/*eslint no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": false }]*/ +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": false }]*/ type SmallPrimes = 2 | 3 | 5 | 7 | 11; ``` @@ -151,7 +36,7 @@ type SmallPrimes = 2 | 3 | 5 | 7 | 11; Examples of **correct** code for the `{ "ignoreNumericLiteralTypes": true }` option: ```ts -/*eslint no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": true }]*/ +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": true }]*/ type SmallPrimes = 2 | 3 | 5 | 7 | 11; ``` diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 9421e39ba21..849bcf57bbb 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -11,15 +11,13 @@ import { JSONSchema4 } from 'json-schema'; type Options = util.InferOptionsTypeFromRule; type MessageIds = util.InferMessageIdsTypeFromRule; -// Original schema properties from the base rule -const { properties } = (baseRule.meta.schema as JSONSchema4[])[0]; - // Extend base schema with additional property to ignore TS numeric literal types -if (properties) { - properties.ignoreNumericLiteralTypes = { +const properties = { + ...(baseRule.meta.schema as JSONSchema4[])[0].properties, + ignoreNumericLiteralTypes: { type: 'boolean', - }; -} + }, +}; export default util.createRule({ name: 'no-magic-numbers', @@ -30,7 +28,7 @@ export default util.createRule({ category: 'Best Practices', recommended: false, }, - schema: baseRule.meta.schema, + schema: { ...baseRule.meta.schema, ...properties }, messages: baseRule.meta.messages, }, defaultOptions: [ @@ -62,7 +60,7 @@ export default util.createRule({ */ function isGrandparentTSTypeAliasDeclaration(node: TSESTree.Node): boolean { return node.parent && node.parent.parent - ? AST_NODE_TYPES.TSTypeAliasDeclaration === node.parent.parent.type + ? node.parent.parent.type === AST_NODE_TYPES.TSTypeAliasDeclaration : false; } @@ -76,7 +74,7 @@ export default util.createRule({ if ( node.parent && node.parent.parent && - AST_NODE_TYPES.TSUnionType === node.parent.parent.type + node.parent.parent.type === AST_NODE_TYPES.TSUnionType ) { return isGrandparentTSTypeAliasDeclaration(node.parent); } @@ -92,7 +90,7 @@ export default util.createRule({ */ function isParentTSLiteralType(node: TSESTree.Node): boolean { return node.parent - ? AST_NODE_TYPES.TSLiteralType === node.parent.type + ? node.parent.type === AST_NODE_TYPES.TSLiteralType : false; } From c188361c3ced730d1ed7ec5d236644fa801d0af3 Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Thu, 28 Mar 2019 12:11:24 +1100 Subject: [PATCH 3/4] feat(eslint-plugin) improve schema extension technique --- .../src/rules/no-magic-numbers.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 849bcf57bbb..9054cfcaac3 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -11,13 +11,7 @@ import { JSONSchema4 } from 'json-schema'; type Options = util.InferOptionsTypeFromRule; type MessageIds = util.InferMessageIdsTypeFromRule; -// Extend base schema with additional property to ignore TS numeric literal types -const properties = { - ...(baseRule.meta.schema as JSONSchema4[])[0].properties, - ignoreNumericLiteralTypes: { - type: 'boolean', - }, -}; +const baseRuleSchema = (baseRule.meta.schema as JSONSchema4[])[0]; export default util.createRule({ name: 'no-magic-numbers', @@ -28,7 +22,16 @@ export default util.createRule({ category: 'Best Practices', recommended: false, }, - schema: { ...baseRule.meta.schema, ...properties }, + // Extend base schema with additional property to ignore TS numeric literal types + schema: [{ + ...baseRuleSchema, + properties: { + ...baseRuleSchema.properties, + ignoreNumericLiteralTypes: { + type: 'boolean', + }, + }, + }], messages: baseRule.meta.messages, }, defaultOptions: [ From 63bae67ad928a99495f606b227f5f78be54da55b Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Wed, 3 Apr 2019 13:37:18 +1100 Subject: [PATCH 4/4] feat(eslint-plugin): formatting --- .../eslint-plugin/src/rules/no-magic-numbers.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 9054cfcaac3..049aa2b35b8 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -23,15 +23,17 @@ export default util.createRule({ recommended: false, }, // Extend base schema with additional property to ignore TS numeric literal types - schema: [{ - ...baseRuleSchema, - properties: { - ...baseRuleSchema.properties, - ignoreNumericLiteralTypes: { - type: 'boolean', + schema: [ + { + ...baseRuleSchema, + properties: { + ...baseRuleSchema.properties, + ignoreNumericLiteralTypes: { + type: 'boolean', + }, }, }, - }], + ], messages: baseRule.meta.messages, }, defaultOptions: [