eslint-config-typed 5.1.3 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.d.mts +14 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.mjs +111 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.d.mts +14 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.d.mts.map +1 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.mjs +113 -0
- package/dist/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.mjs.map +1 -0
- package/dist/plugins/ts-data-forge/rules/rules.d.mts +2 -0
- package/dist/plugins/ts-data-forge/rules/rules.d.mts.map +1 -1
- package/dist/plugins/ts-data-forge/rules/rules.mjs +4 -0
- package/dist/plugins/ts-data-forge/rules/rules.mjs.map +1 -1
- package/dist/rules/eslint-ts-data-forge-rules.d.mts +2 -0
- package/dist/rules/eslint-ts-data-forge-rules.d.mts.map +1 -1
- package/dist/rules/eslint-ts-data-forge-rules.mjs +2 -0
- package/dist/rules/eslint-ts-data-forge-rules.mjs.map +1 -1
- package/dist/rules/eslint-unicorn-rules.d.mts +1 -1
- package/dist/rules/eslint-unicorn-rules.d.mts.map +1 -1
- package/dist/rules/eslint-unicorn-rules.mjs +6 -1
- package/dist/rules/eslint-unicorn-rules.mjs.map +1 -1
- package/dist/types/rules/eslint-ts-data-forge-rules.d.mts +30 -0
- package/dist/types/rules/eslint-ts-data-forge-rules.d.mts.map +1 -1
- package/package.json +1 -1
- package/src/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.mts +166 -0
- package/src/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.test.mts +163 -0
- package/src/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.mts +166 -0
- package/src/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.test.mts +137 -0
- package/src/plugins/ts-data-forge/rules/rules.mts +4 -0
- package/src/rules/eslint-ts-data-forge-rules.mts +2 -0
- package/src/rules/eslint-unicorn-rules.mts +7 -1
- package/src/types/rules/eslint-ts-data-forge-rules.mts +32 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useSafeParseFloat';
|
|
4
|
+
/**
|
|
5
|
+
* Detects `parseFloat(x)`, `Number.parseFloat(x)`, and `Number(x)` (when x
|
|
6
|
+
* is typed as `string`) and replaces them with
|
|
7
|
+
* `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` (ts-data-forge).
|
|
8
|
+
*
|
|
9
|
+
* `Number(x)` is only flagged when x is purely a string type to avoid false
|
|
10
|
+
* positives for `Number(someBoolean)` or `Number(someNumber)` uses.
|
|
11
|
+
*/
|
|
12
|
+
export declare const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=prefer-num-safe-parse-float.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-num-safe-parse-float.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAQlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,mBAAmB,CAAC;AAkBtC;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA6HjE,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns `true` when every constituent of `type` is string-like, i.e. the
|
|
7
|
+
* type is assignable to the `string` parameter of `Num.safeParseFloat`. A
|
|
8
|
+
* union such as `string | undefined` is rejected so the autofix never
|
|
9
|
+
* produces a type error.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
12
|
+
const isStringType = (type) => {
|
|
13
|
+
const parts = type.isUnion() ? type.types : [type];
|
|
14
|
+
return (parts.length > 0 &&
|
|
15
|
+
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0));
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Detects `parseFloat(x)`, `Number.parseFloat(x)`, and `Number(x)` (when x
|
|
19
|
+
* is typed as `string`) and replaces them with
|
|
20
|
+
* `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` (ts-data-forge).
|
|
21
|
+
*
|
|
22
|
+
* `Number(x)` is only flagged when x is purely a string type to avoid false
|
|
23
|
+
* positives for `Number(someBoolean)` or `Number(someNumber)` uses.
|
|
24
|
+
*/
|
|
25
|
+
const preferNumSafeParseFloat = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: 'suggestion',
|
|
28
|
+
docs: {
|
|
29
|
+
description: 'Replace `parseFloat(x)`, `Number.parseFloat(x)`, or `Number(x)` (when x is a string) with `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` from ts-data-forge.',
|
|
30
|
+
},
|
|
31
|
+
fixable: 'code',
|
|
32
|
+
schema: [],
|
|
33
|
+
messages: {
|
|
34
|
+
useSafeParseFloat: 'Replace `{{original}}` with `Result.unwrapOkOr(Num.safeParseFloat({{argName}}), Number.NaN)` from ts-data-forge.',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
create: (context) => {
|
|
38
|
+
const sourceCode = context.sourceCode;
|
|
39
|
+
const program = sourceCode.ast;
|
|
40
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
41
|
+
const services = context.sourceCode.parserServices;
|
|
42
|
+
const mut_nodesToFix = [];
|
|
43
|
+
return {
|
|
44
|
+
CallExpression: (node) => {
|
|
45
|
+
const { callee } = node;
|
|
46
|
+
// Match `parseFloat(...)` (global function).
|
|
47
|
+
const isGlobalParseFloat = callee.type === AST_NODE_TYPES.Identifier &&
|
|
48
|
+
callee.name === 'parseFloat';
|
|
49
|
+
// Match `Number.parseFloat(...)`.
|
|
50
|
+
const isNumberParseFloat = callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
51
|
+
!callee.computed &&
|
|
52
|
+
callee.object.type === AST_NODE_TYPES.Identifier &&
|
|
53
|
+
callee.object.name === 'Number' &&
|
|
54
|
+
callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
55
|
+
callee.property.name === 'parseFloat';
|
|
56
|
+
// Match `Number(...)` called as a function (not `new Number(...)`).
|
|
57
|
+
const isNumberCall = callee.type === AST_NODE_TYPES.Identifier &&
|
|
58
|
+
callee.name === 'Number';
|
|
59
|
+
if (!isGlobalParseFloat && !isNumberParseFloat && !isNumberCall)
|
|
60
|
+
return;
|
|
61
|
+
const args = node.arguments;
|
|
62
|
+
const firstArg = args[0];
|
|
63
|
+
if (firstArg === undefined)
|
|
64
|
+
return;
|
|
65
|
+
// Spread argument (`parseFloat(...rest)`) cannot be rewritten safely.
|
|
66
|
+
if (firstArg.type === AST_NODE_TYPES.SpreadElement)
|
|
67
|
+
return;
|
|
68
|
+
// The argument must be purely `string` so the autofix is type-safe
|
|
69
|
+
// against `Num.safeParseFloat(s: string)`. Without type information,
|
|
70
|
+
// skip.
|
|
71
|
+
if (services?.program == null)
|
|
72
|
+
return;
|
|
73
|
+
const checker = services.program.getTypeChecker();
|
|
74
|
+
const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
|
|
75
|
+
if (tsNode === undefined)
|
|
76
|
+
return;
|
|
77
|
+
const argType = checker.getTypeAtLocation(tsNode);
|
|
78
|
+
if (!isStringType(argType))
|
|
79
|
+
return;
|
|
80
|
+
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
81
|
+
},
|
|
82
|
+
'Program:exit': () => {
|
|
83
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
84
|
+
const missingImports = ['Num', 'Result'].filter((name) => !namedImports.includes(name));
|
|
85
|
+
for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
|
|
86
|
+
const argText = sourceCode.getText(argExpression);
|
|
87
|
+
const originalText = sourceCode.getText(node);
|
|
88
|
+
context.report({
|
|
89
|
+
node,
|
|
90
|
+
messageId: 'useSafeParseFloat',
|
|
91
|
+
data: {
|
|
92
|
+
original: originalText,
|
|
93
|
+
argName: argText,
|
|
94
|
+
},
|
|
95
|
+
fix: (fixer) => {
|
|
96
|
+
const core = `Result.unwrapOkOr(Num.safeParseFloat(${argText}), Number.NaN)`;
|
|
97
|
+
const importFixes = index === 0 && missingImports.length > 0
|
|
98
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, missingImports)
|
|
99
|
+
: [];
|
|
100
|
+
return [...importFixes, fixer.replaceText(node, core)];
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
defaultOptions: [],
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export { preferNumSafeParseFloat };
|
|
111
|
+
//# sourceMappingURL=prefer-num-safe-parse-float.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-num-safe-parse-float.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-num-safe-parse-float.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type Options = readonly [];
|
|
3
|
+
type MessageIds = 'useSafeParseInt';
|
|
4
|
+
/**
|
|
5
|
+
* Detects the base-10 forms of `parseInt` / `Number.parseInt` (`parseInt(x)` or
|
|
6
|
+
* `parseInt(x, 10)`) and replaces them with
|
|
7
|
+
* `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` (ts-data-forge).
|
|
8
|
+
*
|
|
9
|
+
* Other radixes (e.g. `parseInt(x, 16)`) are intentionally left untouched, as
|
|
10
|
+
* `Num.safeParseInt` only supports base 10.
|
|
11
|
+
*/
|
|
12
|
+
export declare const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=prefer-num-safe-parse-int.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-num-safe-parse-int.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAQlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,iBAAiB,CAAC;AAkBpC;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA6HjE,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
import { getTsDataForgeImport, getNamedImports, buildImportFixes } from './import-utils.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns `true` when every constituent of `type` is string-like, i.e. the type
|
|
7
|
+
* is assignable to the `string` parameter of `Num.safeParseInt`. A union such
|
|
8
|
+
* as `string | undefined` is rejected so the autofix never produces a type
|
|
9
|
+
* error.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
12
|
+
const isStringType = (type) => {
|
|
13
|
+
const parts = type.isUnion() ? type.types : [type];
|
|
14
|
+
return (parts.length > 0 &&
|
|
15
|
+
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0));
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Detects the base-10 forms of `parseInt` / `Number.parseInt` (`parseInt(x)` or
|
|
19
|
+
* `parseInt(x, 10)`) and replaces them with
|
|
20
|
+
* `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` (ts-data-forge).
|
|
21
|
+
*
|
|
22
|
+
* Other radixes (e.g. `parseInt(x, 16)`) are intentionally left untouched, as
|
|
23
|
+
* `Num.safeParseInt` only supports base 10.
|
|
24
|
+
*/
|
|
25
|
+
const preferNumSafeParseInt = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: 'suggestion',
|
|
28
|
+
docs: {
|
|
29
|
+
description: 'Replace `parseInt(x, 10)` with `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` from ts-data-forge.',
|
|
30
|
+
},
|
|
31
|
+
fixable: 'code',
|
|
32
|
+
schema: [],
|
|
33
|
+
messages: {
|
|
34
|
+
useSafeParseInt: 'Replace `{{original}}` with `Result.unwrapOkOr(Num.safeParseInt({{argName}}), Number.NaN)` from ts-data-forge.',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
create: (context) => {
|
|
38
|
+
const sourceCode = context.sourceCode;
|
|
39
|
+
const program = sourceCode.ast;
|
|
40
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
41
|
+
const services = context.sourceCode.parserServices;
|
|
42
|
+
const mut_nodesToFix = [];
|
|
43
|
+
return {
|
|
44
|
+
CallExpression: (node) => {
|
|
45
|
+
const { callee } = node;
|
|
46
|
+
// Match `parseInt(...)` or `Number.parseInt(...)`.
|
|
47
|
+
const isGlobalParseInt = callee.type === AST_NODE_TYPES.Identifier &&
|
|
48
|
+
callee.name === 'parseInt';
|
|
49
|
+
const isNumberParseInt = callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
50
|
+
!callee.computed &&
|
|
51
|
+
callee.object.type === AST_NODE_TYPES.Identifier &&
|
|
52
|
+
callee.object.name === 'Number' &&
|
|
53
|
+
callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
54
|
+
callee.property.name === 'parseInt';
|
|
55
|
+
if (!isGlobalParseInt && !isNumberParseInt)
|
|
56
|
+
return;
|
|
57
|
+
const args = node.arguments;
|
|
58
|
+
const firstArg = args[0];
|
|
59
|
+
if (firstArg === undefined)
|
|
60
|
+
return;
|
|
61
|
+
// Spread argument (`parseInt(...rest)`) cannot be rewritten safely.
|
|
62
|
+
if (firstArg.type === AST_NODE_TYPES.SpreadElement)
|
|
63
|
+
return;
|
|
64
|
+
// Only base 10: accept a missing radix or an explicit literal `10`.
|
|
65
|
+
if (args.length >= 2) {
|
|
66
|
+
const radix = args[1];
|
|
67
|
+
if (radix?.type !== AST_NODE_TYPES.Literal || radix.value !== 10) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// The argument must be a `string` so the autofix is type-safe against
|
|
72
|
+
// `Num.safeParseInt(s: string)`. Without type information, skip.
|
|
73
|
+
if (services?.program == null)
|
|
74
|
+
return;
|
|
75
|
+
const checker = services.program.getTypeChecker();
|
|
76
|
+
const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
|
|
77
|
+
if (tsNode === undefined)
|
|
78
|
+
return;
|
|
79
|
+
const argType = checker.getTypeAtLocation(tsNode);
|
|
80
|
+
if (!isStringType(argType))
|
|
81
|
+
return;
|
|
82
|
+
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
83
|
+
},
|
|
84
|
+
'Program:exit': () => {
|
|
85
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
86
|
+
const missingImports = ['Num', 'Result'].filter((name) => !namedImports.includes(name));
|
|
87
|
+
for (const [index, { node, argExpression },] of mut_nodesToFix.entries()) {
|
|
88
|
+
const argText = sourceCode.getText(argExpression);
|
|
89
|
+
const originalText = sourceCode.getText(node);
|
|
90
|
+
context.report({
|
|
91
|
+
node,
|
|
92
|
+
messageId: 'useSafeParseInt',
|
|
93
|
+
data: {
|
|
94
|
+
original: originalText,
|
|
95
|
+
argName: argText,
|
|
96
|
+
},
|
|
97
|
+
fix: (fixer) => {
|
|
98
|
+
const core = `Result.unwrapOkOr(Num.safeParseInt(${argText}), Number.NaN)`;
|
|
99
|
+
const importFixes = index === 0 && missingImports.length > 0
|
|
100
|
+
? buildImportFixes(fixer, program, tsDataForgeImport, missingImports)
|
|
101
|
+
: [];
|
|
102
|
+
return [...importFixes, fixer.replaceText(node, core)];
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
defaultOptions: [],
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { preferNumSafeParseInt };
|
|
113
|
+
//# sourceMappingURL=prefer-num-safe-parse-int.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-num-safe-parse-int.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/prefer-num-safe-parse-int.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export declare const tsDataForgeRules: {
|
|
|
8
8
|
readonly 'prefer-is-non-null-object': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useIsNonNullObject", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
9
9
|
readonly 'prefer-range-for-loop': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useRangeForLoop", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
10
10
|
readonly 'prefer-is-record-and-has-key': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useIsRecordAndHasKey", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
11
|
+
readonly 'prefer-num-safe-parse-int': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useSafeParseInt", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
12
|
+
readonly 'prefer-num-safe-parse-float': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useSafeParseFloat", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
11
13
|
readonly 'no-unnecessary-type-guard': import("@typescript-eslint/utils/ts-eslint").RuleModule<"alwaysTrue" | "alwaysFalse" | "replaceTypeGuard", readonly [(Readonly<{
|
|
12
14
|
ignore?: readonly string[];
|
|
13
15
|
}> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/rules.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-data-forge/rules/rules.mts"],"names":[],"mappings":"AAeA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAca,CAAC"}
|
|
@@ -8,6 +8,8 @@ import { preferAsInt } from './prefer-as-int.mjs';
|
|
|
8
8
|
import { preferComparisonOverNullishGuard } from './prefer-comparison-over-nullish-guard.mjs';
|
|
9
9
|
import { preferIsNonNullObject } from './prefer-is-non-null-object.mjs';
|
|
10
10
|
import { preferIsRecordAndHasKey } from './prefer-is-record-and-has-key.mjs';
|
|
11
|
+
import { preferNumSafeParseFloat } from './prefer-num-safe-parse-float.mjs';
|
|
12
|
+
import { preferNumSafeParseInt } from './prefer-num-safe-parse-int.mjs';
|
|
11
13
|
import { preferRangeForLoop } from './prefer-range-for-loop.mjs';
|
|
12
14
|
|
|
13
15
|
const tsDataForgeRules = {
|
|
@@ -20,6 +22,8 @@ const tsDataForgeRules = {
|
|
|
20
22
|
'prefer-is-non-null-object': preferIsNonNullObject,
|
|
21
23
|
'prefer-range-for-loop': preferRangeForLoop,
|
|
22
24
|
'prefer-is-record-and-has-key': preferIsRecordAndHasKey,
|
|
25
|
+
'prefer-num-safe-parse-int': preferNumSafeParseInt,
|
|
26
|
+
'prefer-num-safe-parse-float': preferNumSafeParseFloat,
|
|
23
27
|
'no-unnecessary-type-guard': noUnnecessaryTypeGuard,
|
|
24
28
|
'prefer-comparison-over-nullish-guard': preferComparisonOverNullishGuard,
|
|
25
29
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/ts-data-forge/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;;;AAeO,MAAM,gBAAgB,GAAG;AAC9B,IAAA,qCAAqC,EAAE,6BAA6B;AACpE,IAAA,+BAA+B,EAAE,wBAAwB;AACzD,IAAA,qBAAqB,EAAE,gBAAgB;AACvC,IAAA,yBAAyB,EAAE,mBAAmB;AAC9C,IAAA,gBAAgB,EAAE,YAAY;AAC9B,IAAA,eAAe,EAAE,WAAW;AAC5B,IAAA,2BAA2B,EAAE,qBAAqB;AAClD,IAAA,uBAAuB,EAAE,kBAAkB;AAC3C,IAAA,8BAA8B,EAAE,uBAAuB;AACvD,IAAA,2BAA2B,EAAE,qBAAqB;AAClD,IAAA,6BAA6B,EAAE,uBAAuB;AACtD,IAAA,2BAA2B,EAAE,sBAAsB;AACnD,IAAA,sCAAsC,EAAE,gCAAgC;;;;;"}
|
|
@@ -8,6 +8,8 @@ export declare const eslintTsDataForgeRules: {
|
|
|
8
8
|
readonly 'ts-data-forge/prefer-arr-is-array-at-least-length': "error";
|
|
9
9
|
readonly 'ts-data-forge/prefer-arr-is-array-of-length': "error";
|
|
10
10
|
readonly 'ts-data-forge/prefer-is-record-and-has-key': "error";
|
|
11
|
+
readonly 'ts-data-forge/prefer-num-safe-parse-int': "error";
|
|
12
|
+
readonly 'ts-data-forge/prefer-num-safe-parse-float': "error";
|
|
11
13
|
readonly 'ts-data-forge/no-unnecessary-type-guard': 2 | 1;
|
|
12
14
|
readonly 'ts-data-forge/prefer-comparison-over-nullish-guard': "error";
|
|
13
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-data-forge-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-data-forge-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"eslint-ts-data-forge-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-data-forge-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;CAcQ,CAAC"}
|
|
@@ -10,6 +10,8 @@ const eslintTsDataForgeRules = {
|
|
|
10
10
|
'ts-data-forge/prefer-arr-is-array-at-least-length': 'error',
|
|
11
11
|
'ts-data-forge/prefer-arr-is-array-of-length': 'error',
|
|
12
12
|
'ts-data-forge/prefer-is-record-and-has-key': 'error',
|
|
13
|
+
'ts-data-forge/prefer-num-safe-parse-int': 'error',
|
|
14
|
+
'ts-data-forge/prefer-num-safe-parse-float': 'error',
|
|
13
15
|
'ts-data-forge/no-unnecessary-type-guard': withDefaultOption('error'),
|
|
14
16
|
'ts-data-forge/prefer-comparison-over-nullish-guard': 'error',
|
|
15
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-data-forge-rules.mjs","sources":["../../src/rules/eslint-ts-data-forge-rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAKO,MAAM,sBAAsB,GAAG;AACpC,IAAA,6BAA6B,EAAE,OAAO;AACtC,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,mDAAmD,EAAE,OAAO;AAC5D,IAAA,6CAA6C,EAAE,OAAO;AACtD,IAAA,4CAA4C,EAAE,OAAO;AACrD,IAAA,yCAAyC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACrE,IAAA,oDAAoD,EAAE,OAAO;;;;;"}
|
|
1
|
+
{"version":3,"file":"eslint-ts-data-forge-rules.mjs","sources":["../../src/rules/eslint-ts-data-forge-rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAKO,MAAM,sBAAsB,GAAG;AACpC,IAAA,6BAA6B,EAAE,OAAO;AACtC,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,mDAAmD,EAAE,OAAO;AAC5D,IAAA,6CAA6C,EAAE,OAAO;AACtD,IAAA,4CAA4C,EAAE,OAAO;AACrD,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,yCAAyC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACrE,IAAA,oDAAoD,EAAE,OAAO;;;;;"}
|
|
@@ -231,7 +231,7 @@ export declare const eslintUnicornRules: {
|
|
|
231
231
|
readonly 'unicorn/prefer-iterator-to-array-at-end': "error";
|
|
232
232
|
readonly 'unicorn/prefer-math-abs': "error";
|
|
233
233
|
readonly 'unicorn/prefer-minimal-ternary': "off";
|
|
234
|
-
readonly 'unicorn/prefer-number-coercion': "
|
|
234
|
+
readonly 'unicorn/prefer-number-coercion': "off";
|
|
235
235
|
readonly 'unicorn/prefer-number-is-safe-integer': "error";
|
|
236
236
|
readonly 'unicorn/prefer-object-define-properties': "error";
|
|
237
237
|
readonly 'unicorn/prefer-object-destructuring-defaults': "error";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-unicorn-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-unicorn-rules.mts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB;IAC7B;;;;OAIG;;;;;IAOH,iDAAiD;;;;;;;;IAUjD,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA0HrC;;;;;OAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"eslint-unicorn-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-unicorn-rules.mts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB;IAC7B;;;;OAIG;;;;;IAOH,iDAAiD;;;;;;;;IAUjD,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA0HrC;;;;;OAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoPkC,CAAC"}
|
|
@@ -277,7 +277,12 @@ const eslintUnicornRules = {
|
|
|
277
277
|
'unicorn/prefer-math-abs': 'error',
|
|
278
278
|
// This rule is disabled because it would require the container to be directly included in the React hooks dependencies.
|
|
279
279
|
'unicorn/prefer-minimal-ternary': 'off',
|
|
280
|
-
|
|
280
|
+
// Disabled in favor of `ts-data-forge/prefer-num-safe-parse-int`, which
|
|
281
|
+
// rewrites `parseInt(x, 10)` to `Num.safeParseInt(x)` instead of
|
|
282
|
+
// `Math.trunc(Number(x))`. The latter is hard to read and silently changes
|
|
283
|
+
// parsing semantics (e.g. `Number('')` is `0` whereas `parseInt('', 10)` is
|
|
284
|
+
// `NaN`).
|
|
285
|
+
'unicorn/prefer-number-coercion': 'off',
|
|
281
286
|
'unicorn/prefer-number-is-safe-integer': 'error',
|
|
282
287
|
'unicorn/prefer-object-define-properties': 'error',
|
|
283
288
|
'unicorn/prefer-object-destructuring-defaults': 'error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-unicorn-rules.mjs","sources":["../../src/rules/eslint-unicorn-rules.mts"],"sourcesContent":[null],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"eslint-unicorn-rules.mjs","sources":["../../src/rules/eslint-unicorn-rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAEO,MAAM,kBAAkB,GAAG;AAChC;;;;AAIG;AACH,IAAA,4BAA4B,EAAE,KAAK;AACnC,IAAA,2BAA2B,EAAE,KAAK;AAClC,IAAA,6BAA6B,EAAE,KAAK;AAEpC,IAAA,0BAA0B,EAAE,iBAAiB,CAAC,OAAO,CAAC;;AAGtD,IAAA,kCAAkC,EAAE,OAAO;AAE3C,IAAA,qCAAqC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACjE,IAAA,iCAAiC,EAAE,KAAK;AACxC,IAAA,uBAAuB,EAAE,OAAO;AAChC,IAAA,qBAAqB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACjD,IAAA,gCAAgC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC5D,IAAA,+BAA+B,EAAE,KAAK;;AAGtC,IAAA,uBAAuB,EAAE;QACvB,OAAO;AACP,QAAA;AACE,YAAA,IAAI,EAAE,WAAW;AACjB,YAAA,MAAM,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC;AAC9C,SAAA;AACF,KAAA;AAED,IAAA,sBAAsB,EAAE;QACtB,OAAO;AACP,QAAA;AACE,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE;AACJ,oBAAA,SAAS,EAAE,IAAI;AACf,oBAAA,KAAK,EAAE,KAAK;AACb,iBAAA;AACD,gBAAA,WAAW,EAAE;AACX,oBAAA,SAAS,EAAE,IAAI;AACf,oBAAA,KAAK,EAAE,KAAK;AACb,iBAAA;AACD,gBAAA,IAAI,EAAE;AACJ,oBAAA,SAAS,EAAE,IAAI;AACf,oBAAA,KAAK,EAAE,KAAK;AACb,iBAAA;AACD,gBAAA,WAAW,EAAE;AACX,oBAAA,SAAS,EAAE,IAAI;AACf,oBAAA,KAAK,EAAE,KAAK;AACb,iBAAA;AACF,aAAA;AACF,SAAA;AACF,KAAA;IAED,uBAAuB,EAAE,KAAK;AAC9B,IAAA,sBAAsB,EAAE,OAAO;AAC/B,IAAA,0BAA0B,EAAE,OAAO;AAEnC,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,qCAAqC,EAAE,KAAK;IAC5C,uCAAuC,EAAE,KAAK;AAC9C,IAAA,yBAAyB,EAAE,KAAK;AAChC,IAAA,oCAAoC,EAAE,OAAO;IAC7C,2BAA2B,EAAE,KAAK;AAClC,IAAA,uBAAuB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACnD,IAAA,qBAAqB,EAAE,OAAO;IAC9B,2BAA2B,EAAE,KAAK;AAClC,IAAA,sBAAsB,EAAE,OAAO;AAC/B,IAAA,8BAA8B,EAAE,KAAK;AACrC,IAAA,iBAAiB,EAAE,KAAK;AACxB,IAAA,wCAAwC,EAAE,OAAO;AACjD,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,qBAAqB,EAAE,OAAO;AAC9B,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,6BAA6B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACzD,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,2CAA2C,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACvE,IAAA,8BAA8B,EAAE,OAAO;;;;;AAKvC,IAAA,uCAAuC,EAAE,KAAK;AAC9C,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,2BAA2B,EAAE,OAAO;IACpC,8BAA8B,EAAE,KAAK;AACrC,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,kCAAkC,EAAE,KAAK;IACzC,2BAA2B,EAAE,KAAK;AAClC,IAAA,2BAA2B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACvD,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,2BAA2B,EAAE,OAAO;;AAEpC,IAAA,mBAAmB,EAAE;QACnB,OAAO;AACP,QAAA;AACE,YAAA,mBAAmB,EAAE,KAAK;AAC3B,SAAA;AACF,KAAA;AACD,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,yBAAyB,EAAE,OAAO;AAClC,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACxD,IAAA,yBAAyB,EAAE,OAAO;;AAGlC,IAAA,2BAA2B,EAAE,KAAK;AAElC,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,kCAAkC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC9D,IAAA,oCAAoC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAChE,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,wBAAwB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACpD,IAAA,yBAAyB,EAAE,OAAO;AAClC,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,6BAA6B,EAAE,OAAO;AACtC,IAAA,wCAAwC,EAAE,OAAO;AACjD,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,uBAAuB,EAAE;QACvB,OAAO;AACP,QAAA,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,EAAE,iBAAiB,EAAE;AACzD,KAAA;AACD,IAAA,wBAAwB,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;AACvD,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,+BAA+B,EAAE,KAAK;AACtC,IAAA,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACxD,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,iDAAiD,EAAE,OAAO;AAC1D,IAAA,wBAAwB,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACpD,4BAA4B,EAAE,KAAK;AACnC,IAAA,yBAAyB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACrD,IAAA,uCAAuC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACnE,IAAA,yBAAyB,EAAE,OAAO;AAClC,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,iCAAiC,EAAE,OAAO;AAE1C;;;;;AAKG;AACH,IAAA,0CAA0C,EAAE,KAAK;AAEjD,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,kCAAkC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC9D,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,iCAAiC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC7D,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,0CAA0C,EAAE,OAAO;AACnD,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,6BAA6B,EAAE,OAAO;AAEtC,IAAA,gCAAgC,EAAE;QAChC,OAAO;AACP,QAAA;AACE,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,eAAe,EAAE,IAAI;AACtB,SAAA;AACF,KAAA;AACD,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,0BAA0B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACtD,IAAA,uBAAuB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACnD,IAAA,0BAA0B,EAAE,OAAO;AACnC,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,6BAA6B,EAAE,OAAO;AACtC,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACxD,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,mCAAmC,EAAE,OAAO;AAE5C,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,wCAAwC,EAAE,OAAO;AACjD,IAAA,4BAA4B,EAAE,KAAK;AACnC,IAAA,4CAA4C,EAAE,OAAO;AACrD,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,oCAAoC,EAAE,OAAO;;AAG7C,IAAA,2CAA2C,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACvE,IAAA,yBAAyB,EAAE,KAAK;;;;;;;;;;;;;;AAchC,IAAA,uCAAuC,EAAE,iBAAiB,CAAC,OAAO,CAAC;;AAGnE,IAAA,mCAAmC,EAAE,KAAK;AAE1C,IAAA,8CAA8C,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC1E,IAAA,mCAAmC,EAAE,KAAK;AAC1C,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,8BAA8B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC1D,IAAA,kBAAkB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC9C,IAAA,0BAA0B,EAAE,KAAK;IACjC,2CAA2C,EAAE,OAAO;AACpD,IAAA,4BAA4B,EAAE,OAAO;;AAErC,IAAA,sDAAsD,EAAE,KAAK;AAC7D,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,qBAAqB,EAAE,OAAO;AAC9B,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,oDAAoD,EAAE,OAAO;AAC7D,IAAA,mCAAmC,EAAE,OAAO;;;AAG5C,IAAA,sCAAsC,EAAE,KAAK;AAC7C,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,oCAAoC,EAAE,OAAO;AAC7C,IAAA,+BAA+B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC3D,IAAA,4CAA4C,EAAE,OAAO;AACrD,IAAA,qDAAqD,EAAE,OAAO;AAC9D,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,kCAAkC,EAAE,OAAO;;AAG3C,IAAA,mCAAmC,EAAE,KAAK;AAE1C,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,oCAAoC,EAAE,OAAO;AAC7C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,4CAA4C,EAAE,OAAO;;AAGrD,IAAA,gCAAgC,EAAE,KAAK;AAEvC,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,2BAA2B,EAAE,OAAO;AACpC,IAAA,yBAAyB,EAAE,OAAO;AAClC,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,mCAAmC,EAAE,OAAO;;;AAI5C,IAAA,sBAAsB,EAAE,KAAK;AAE7B,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,wBAAwB,EAAE,OAAO;AACjC,IAAA,6BAA6B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACzD,IAAA,uCAAuC,EAAE,OAAO;;AAGhD,IAAA,wCAAwC,EAAE,KAAK;;AAG/C,IAAA,sBAAsB,EAAE,KAAK;AAE7B,IAAA,oDAAoD,EAAE,OAAO;;AAG7D,IAAA,mDAAmD,EAAE,KAAK;AAE1D,IAAA,wCAAwC,EAAE,OAAO;AACjD,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,yBAAyB,EAAE,OAAO;;AAGlC,IAAA,gCAAgC,EAAE,KAAK;;;;;;AAOvC,IAAA,gCAAgC,EAAE,KAAK;AAEvC,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,yCAAyC,EAAE,OAAO;AAClD,IAAA,8CAA8C,EAAE,OAAO;AACvD,IAAA,wCAAwC,EAAE,OAAO;AACjD,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,gCAAgC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC5D,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,4CAA4C,EAAE,OAAO;AACrD,IAAA,8BAA8B,EAAE,OAAO;AACvC,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,8BAA8B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC1D,IAAA,yBAAyB,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACrD,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,yBAAyB,EAAE,OAAO;;AAGlC,IAAA,oCAAoC,EAAE,KAAK;AAE3C,IAAA,2CAA2C,EAAE,OAAO;;AAGpD,IAAA,wBAAwB,EAAE,KAAK;;AAG/B,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,kCAAkC,EAAE,OAAO;AAC3C,IAAA,0CAA0C,EAAE,OAAO;AACnD,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,iCAAiC,EAAE,OAAO;AAC1C,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,0BAA0B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACtD,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,6BAA6B,EAAE,OAAO;AACtC,IAAA,mCAAmC,EAAE,OAAO;AAC5C,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,+BAA+B,EAAE,iBAAiB,CAAC,OAAO,CAAC;;;AAG3D,IAAA,4CAA4C,EAAE,KAAK;AACnD,IAAA,mCAAmC,EAAE,iBAAiB,CAAC,OAAO,CAAC;AAC/D,IAAA,+BAA+B,EAAE,OAAO;AACxC,IAAA,yBAAyB,EAAE,OAAO;AAClC,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,qCAAqC,EAAE,OAAO;AAC9C,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,uCAAuC,EAAE,OAAO;AAChD,IAAA,4BAA4B,EAAE,OAAO;AACrC,IAAA,2CAA2C,EAAE,OAAO;AACpD,IAAA,sCAAsC,EAAE,OAAO;AAC/C,IAAA,gCAAgC,EAAE,OAAO;AACzC,IAAA,uBAAuB,EAAE,OAAO;AAChC,IAAA,gCAAgC,EAAE,OAAO;IACzC,qCAAqC,EAAE,OAAO;AAC9C,IAAA,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,CAAC;AACxD,IAAA,gCAAgC,EAAE,OAAO;;AAGzC,IAAA,uBAAuB,EAAE,OAAO;AAChC,IAAA,yBAAyB,EAAE,KAAK;AAChC,IAAA,uBAAuB,EAAE,OAAO;AAChC,IAAA,8BAA8B,EAAE,OAAO;IACvC,qCAAqC,EAAE,OAAO;AAC9C,IAAA,mCAAmC,EAAE,iBAAiB,CAAC,OAAO,CAAC;IAC/D,+BAA+B,EAAE,OAAO;;AAGxC,IAAA,kCAAkC,EAAE,CAAC;IACrC,sBAAsB,EAAE,CAAC;IACzB,uBAAuB,EAAE,CAAC;IAC1B,iCAAiC,EAAE,CAAC;AACpC,IAAA,4BAA4B,EAAE,CAAC;AAC/B,IAAA,6BAA6B,EAAE,CAAC;AAChC,IAAA,gCAAgC,EAAE,CAAC;;;;;"}
|
|
@@ -126,6 +126,34 @@ declare namespace PreferRangeForLoop {
|
|
|
126
126
|
declare namespace PreferIsRecordAndHasKey {
|
|
127
127
|
type RuleEntry = Linter.StringSeverity;
|
|
128
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* @description Replace `parseInt(x, 10)` with `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` from ts-data-forge.
|
|
131
|
+
*
|
|
132
|
+
* ```md
|
|
133
|
+
* | key | value |
|
|
134
|
+
* | :--------- | :--------- |
|
|
135
|
+
* | type | suggestion |
|
|
136
|
+
* | deprecated | false |
|
|
137
|
+
* | fixable | code |
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
declare namespace PreferNumSafeParseInt {
|
|
141
|
+
type RuleEntry = Linter.StringSeverity;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* @description Replace `parseFloat(x)`, `Number.parseFloat(x)`, or `Number(x)` (when x is a string) with `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` from ts-data-forge.
|
|
145
|
+
*
|
|
146
|
+
* ```md
|
|
147
|
+
* | key | value |
|
|
148
|
+
* | :--------- | :--------- |
|
|
149
|
+
* | type | suggestion |
|
|
150
|
+
* | deprecated | false |
|
|
151
|
+
* | fixable | code |
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
declare namespace PreferNumSafeParseFloat {
|
|
155
|
+
type RuleEntry = Linter.StringSeverity;
|
|
156
|
+
}
|
|
129
157
|
/**
|
|
130
158
|
* @description Detect ts-data-forge type guard calls that perform no narrowing (the argument type already satisfies, or can never satisfy, the guard).
|
|
131
159
|
*
|
|
@@ -191,6 +219,8 @@ export type EslintTsDataForgeRules = Readonly<{
|
|
|
191
219
|
'ts-data-forge/prefer-is-non-null-object': PreferIsNonNullObject.RuleEntry;
|
|
192
220
|
'ts-data-forge/prefer-range-for-loop': PreferRangeForLoop.RuleEntry;
|
|
193
221
|
'ts-data-forge/prefer-is-record-and-has-key': PreferIsRecordAndHasKey.RuleEntry;
|
|
222
|
+
'ts-data-forge/prefer-num-safe-parse-int': PreferNumSafeParseInt.RuleEntry;
|
|
223
|
+
'ts-data-forge/prefer-num-safe-parse-float': PreferNumSafeParseFloat.RuleEntry;
|
|
194
224
|
'ts-data-forge/no-unnecessary-type-guard': NoUnnecessaryTypeGuard.RuleEntry;
|
|
195
225
|
'ts-data-forge/prefer-comparison-over-nullish-guard': PreferComparisonOverNullishGuard.RuleEntry;
|
|
196
226
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-ts-data-forge-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-data-forge-rules.mts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eslint-ts-data-forge-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-data-forge-rules.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AST_NODE_TYPES,
|
|
3
|
+
type TSESLint,
|
|
4
|
+
type TSESTree,
|
|
5
|
+
} from '@typescript-eslint/utils';
|
|
6
|
+
import * as ts from 'typescript';
|
|
7
|
+
import {
|
|
8
|
+
buildImportFixes,
|
|
9
|
+
getNamedImports,
|
|
10
|
+
getTsDataForgeImport,
|
|
11
|
+
} from './import-utils.mjs';
|
|
12
|
+
|
|
13
|
+
type Options = readonly [];
|
|
14
|
+
|
|
15
|
+
type MessageIds = 'useSafeParseFloat';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Returns `true` when every constituent of `type` is string-like, i.e. the
|
|
19
|
+
* type is assignable to the `string` parameter of `Num.safeParseFloat`. A
|
|
20
|
+
* union such as `string | undefined` is rejected so the autofix never
|
|
21
|
+
* produces a type error.
|
|
22
|
+
*/
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
24
|
+
const isStringType = (type: ts.Type): boolean => {
|
|
25
|
+
const parts = type.isUnion() ? type.types : ([type] as const);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
parts.length > 0 &&
|
|
29
|
+
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0)
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Detects `parseFloat(x)`, `Number.parseFloat(x)`, and `Number(x)` (when x
|
|
35
|
+
* is typed as `string`) and replaces them with
|
|
36
|
+
* `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` (ts-data-forge).
|
|
37
|
+
*
|
|
38
|
+
* `Number(x)` is only flagged when x is purely a string type to avoid false
|
|
39
|
+
* positives for `Number(someBoolean)` or `Number(someNumber)` uses.
|
|
40
|
+
*/
|
|
41
|
+
export const preferNumSafeParseFloat: TSESLint.RuleModule<MessageIds, Options> =
|
|
42
|
+
{
|
|
43
|
+
meta: {
|
|
44
|
+
type: 'suggestion',
|
|
45
|
+
docs: {
|
|
46
|
+
description:
|
|
47
|
+
'Replace `parseFloat(x)`, `Number.parseFloat(x)`, or `Number(x)` (when x is a string) with `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` from ts-data-forge.',
|
|
48
|
+
},
|
|
49
|
+
fixable: 'code',
|
|
50
|
+
schema: [],
|
|
51
|
+
messages: {
|
|
52
|
+
useSafeParseFloat:
|
|
53
|
+
'Replace `{{original}}` with `Result.unwrapOkOr(Num.safeParseFloat({{argName}}), Number.NaN)` from ts-data-forge.',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
create: (context) => {
|
|
58
|
+
const sourceCode = context.sourceCode;
|
|
59
|
+
|
|
60
|
+
const program = sourceCode.ast;
|
|
61
|
+
|
|
62
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
63
|
+
|
|
64
|
+
const services = context.sourceCode.parserServices;
|
|
65
|
+
|
|
66
|
+
const mut_nodesToFix: {
|
|
67
|
+
node: TSESTree.CallExpression;
|
|
68
|
+
argExpression: TSESTree.Expression;
|
|
69
|
+
}[] = [];
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
CallExpression: (node) => {
|
|
73
|
+
const { callee } = node;
|
|
74
|
+
|
|
75
|
+
// Match `parseFloat(...)` (global function).
|
|
76
|
+
const isGlobalParseFloat =
|
|
77
|
+
callee.type === AST_NODE_TYPES.Identifier &&
|
|
78
|
+
callee.name === 'parseFloat';
|
|
79
|
+
|
|
80
|
+
// Match `Number.parseFloat(...)`.
|
|
81
|
+
const isNumberParseFloat =
|
|
82
|
+
callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
83
|
+
!callee.computed &&
|
|
84
|
+
callee.object.type === AST_NODE_TYPES.Identifier &&
|
|
85
|
+
callee.object.name === 'Number' &&
|
|
86
|
+
callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
87
|
+
callee.property.name === 'parseFloat';
|
|
88
|
+
|
|
89
|
+
// Match `Number(...)` called as a function (not `new Number(...)`).
|
|
90
|
+
const isNumberCall =
|
|
91
|
+
callee.type === AST_NODE_TYPES.Identifier &&
|
|
92
|
+
callee.name === 'Number';
|
|
93
|
+
|
|
94
|
+
if (!isGlobalParseFloat && !isNumberParseFloat && !isNumberCall)
|
|
95
|
+
return;
|
|
96
|
+
|
|
97
|
+
const args = node.arguments;
|
|
98
|
+
|
|
99
|
+
const firstArg = args[0];
|
|
100
|
+
|
|
101
|
+
if (firstArg === undefined) return;
|
|
102
|
+
|
|
103
|
+
// Spread argument (`parseFloat(...rest)`) cannot be rewritten safely.
|
|
104
|
+
if (firstArg.type === AST_NODE_TYPES.SpreadElement) return;
|
|
105
|
+
|
|
106
|
+
// The argument must be purely `string` so the autofix is type-safe
|
|
107
|
+
// against `Num.safeParseFloat(s: string)`. Without type information,
|
|
108
|
+
// skip.
|
|
109
|
+
if (services?.program == null) return;
|
|
110
|
+
|
|
111
|
+
const checker = services.program.getTypeChecker();
|
|
112
|
+
|
|
113
|
+
const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
|
|
114
|
+
|
|
115
|
+
if (tsNode === undefined) return;
|
|
116
|
+
|
|
117
|
+
const argType = checker.getTypeAtLocation(tsNode);
|
|
118
|
+
|
|
119
|
+
if (!isStringType(argType)) return;
|
|
120
|
+
|
|
121
|
+
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
122
|
+
},
|
|
123
|
+
'Program:exit': () => {
|
|
124
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
125
|
+
|
|
126
|
+
const missingImports = (['Num', 'Result'] as const).filter(
|
|
127
|
+
(name) => !namedImports.includes(name),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
for (const [
|
|
131
|
+
index,
|
|
132
|
+
{ node, argExpression },
|
|
133
|
+
] of mut_nodesToFix.entries()) {
|
|
134
|
+
const argText = sourceCode.getText(argExpression);
|
|
135
|
+
|
|
136
|
+
const originalText = sourceCode.getText(node);
|
|
137
|
+
|
|
138
|
+
context.report({
|
|
139
|
+
node,
|
|
140
|
+
messageId: 'useSafeParseFloat',
|
|
141
|
+
data: {
|
|
142
|
+
original: originalText,
|
|
143
|
+
argName: argText,
|
|
144
|
+
},
|
|
145
|
+
fix: (fixer) => {
|
|
146
|
+
const core = `Result.unwrapOkOr(Num.safeParseFloat(${argText}), Number.NaN)`;
|
|
147
|
+
|
|
148
|
+
const importFixes =
|
|
149
|
+
index === 0 && missingImports.length > 0
|
|
150
|
+
? buildImportFixes(
|
|
151
|
+
fixer,
|
|
152
|
+
program,
|
|
153
|
+
tsDataForgeImport,
|
|
154
|
+
missingImports,
|
|
155
|
+
)
|
|
156
|
+
: [];
|
|
157
|
+
|
|
158
|
+
return [...importFixes, fixer.replaceText(node, core)];
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
defaultOptions: [],
|
|
166
|
+
} as const;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import dedent from 'dedent';
|
|
4
|
+
import { preferNumSafeParseFloat } from './prefer-num-safe-parse-float.mjs';
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2020,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
projectService: {
|
|
13
|
+
allowDefaultProject: ['*.ts*'],
|
|
14
|
+
},
|
|
15
|
+
tsconfigRootDir: `${import.meta.dirname}/../..`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('prefer-num-safe-parse-float', () => {
|
|
21
|
+
tester.run('prefer-num-safe-parse-float', preferNumSafeParseFloat, {
|
|
22
|
+
valid: [
|
|
23
|
+
{
|
|
24
|
+
name: 'ignores number arguments to Number() (autofix would be unsafe)',
|
|
25
|
+
code: dedent`
|
|
26
|
+
const x = 42;
|
|
27
|
+
const n = Number(x);
|
|
28
|
+
`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'ignores boolean arguments to Number()',
|
|
32
|
+
code: dedent`
|
|
33
|
+
const b = true;
|
|
34
|
+
const n = Number(b);
|
|
35
|
+
`,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'ignores never-typed arguments (string & number = never)',
|
|
39
|
+
code: dedent`
|
|
40
|
+
declare const x: string & number;
|
|
41
|
+
const n = parseFloat(x);
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'ignores spread arguments',
|
|
46
|
+
code: dedent`
|
|
47
|
+
declare const args: [string];
|
|
48
|
+
const n = parseFloat(...args);
|
|
49
|
+
`,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'ignores parseInt (handled by prefer-num-safe-parse-int)',
|
|
53
|
+
code: dedent`
|
|
54
|
+
const s = "123";
|
|
55
|
+
const n = parseInt(s, 10);
|
|
56
|
+
`,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
invalid: [
|
|
60
|
+
{
|
|
61
|
+
name: 'replaces parseFloat(s) and imports Num + Result',
|
|
62
|
+
code: dedent`
|
|
63
|
+
const s = "3.14";
|
|
64
|
+
const n = parseFloat(s);
|
|
65
|
+
`,
|
|
66
|
+
output: dedent`
|
|
67
|
+
import { Num, Result } from 'ts-data-forge';
|
|
68
|
+
const s = "3.14";
|
|
69
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
70
|
+
`,
|
|
71
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'replaces Number.parseFloat(s)',
|
|
75
|
+
code: dedent`
|
|
76
|
+
const s = "3.14";
|
|
77
|
+
const n = Number.parseFloat(s);
|
|
78
|
+
`,
|
|
79
|
+
output: dedent`
|
|
80
|
+
import { Num, Result } from 'ts-data-forge';
|
|
81
|
+
const s = "3.14";
|
|
82
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
83
|
+
`,
|
|
84
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'replaces Number(s) when s is a string',
|
|
88
|
+
code: dedent`
|
|
89
|
+
const s = "3.14";
|
|
90
|
+
const n = Number(s);
|
|
91
|
+
`,
|
|
92
|
+
output: dedent`
|
|
93
|
+
import { Num, Result } from 'ts-data-forge';
|
|
94
|
+
const s = "3.14";
|
|
95
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
96
|
+
`,
|
|
97
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'adds only the missing Result import when Num is present',
|
|
101
|
+
code: dedent`
|
|
102
|
+
import { Num } from 'ts-data-forge';
|
|
103
|
+
|
|
104
|
+
const s = "3.14";
|
|
105
|
+
const n = parseFloat(s);
|
|
106
|
+
`,
|
|
107
|
+
output: dedent`
|
|
108
|
+
import { Result } from 'ts-data-forge';
|
|
109
|
+
import { Num } from 'ts-data-forge';
|
|
110
|
+
|
|
111
|
+
const s = "3.14";
|
|
112
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
113
|
+
`,
|
|
114
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'preserves a complex string argument expression',
|
|
118
|
+
code: dedent`
|
|
119
|
+
const get = (k: string): string => k;
|
|
120
|
+
const n = parseFloat(get("x").trim());
|
|
121
|
+
`,
|
|
122
|
+
output: dedent`
|
|
123
|
+
import { Num, Result } from 'ts-data-forge';
|
|
124
|
+
const get = (k: string): string => k;
|
|
125
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat(get("x").trim()), Number.NaN);
|
|
126
|
+
`,
|
|
127
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'replaces Number(s) with a string literal argument',
|
|
131
|
+
code: dedent`
|
|
132
|
+
const n = Number("3.14");
|
|
133
|
+
`,
|
|
134
|
+
output: dedent`
|
|
135
|
+
import { Num, Result } from 'ts-data-forge';
|
|
136
|
+
const n = Result.unwrapOkOr(Num.safeParseFloat("3.14"), Number.NaN);
|
|
137
|
+
`,
|
|
138
|
+
errors: [{ messageId: 'useSafeParseFloat' }],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'replaces all three forms in one file',
|
|
142
|
+
code: dedent`
|
|
143
|
+
const s = "1.5";
|
|
144
|
+
const a = parseFloat(s);
|
|
145
|
+
const b = Number.parseFloat(s);
|
|
146
|
+
const c = Number(s);
|
|
147
|
+
`,
|
|
148
|
+
output: dedent`
|
|
149
|
+
import { Num, Result } from 'ts-data-forge';
|
|
150
|
+
const s = "1.5";
|
|
151
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
152
|
+
const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
153
|
+
const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
154
|
+
`,
|
|
155
|
+
errors: [
|
|
156
|
+
{ messageId: 'useSafeParseFloat' },
|
|
157
|
+
{ messageId: 'useSafeParseFloat' },
|
|
158
|
+
{ messageId: 'useSafeParseFloat' },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
});
|
|
163
|
+
}, 20000);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AST_NODE_TYPES,
|
|
3
|
+
type TSESLint,
|
|
4
|
+
type TSESTree,
|
|
5
|
+
} from '@typescript-eslint/utils';
|
|
6
|
+
import * as ts from 'typescript';
|
|
7
|
+
import {
|
|
8
|
+
buildImportFixes,
|
|
9
|
+
getNamedImports,
|
|
10
|
+
getTsDataForgeImport,
|
|
11
|
+
} from './import-utils.mjs';
|
|
12
|
+
|
|
13
|
+
type Options = readonly [];
|
|
14
|
+
|
|
15
|
+
type MessageIds = 'useSafeParseInt';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Returns `true` when every constituent of `type` is string-like, i.e. the type
|
|
19
|
+
* is assignable to the `string` parameter of `Num.safeParseInt`. A union such
|
|
20
|
+
* as `string | undefined` is rejected so the autofix never produces a type
|
|
21
|
+
* error.
|
|
22
|
+
*/
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
24
|
+
const isStringType = (type: ts.Type): boolean => {
|
|
25
|
+
const parts = type.isUnion() ? type.types : ([type] as const);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
parts.length > 0 &&
|
|
29
|
+
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0)
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Detects the base-10 forms of `parseInt` / `Number.parseInt` (`parseInt(x)` or
|
|
35
|
+
* `parseInt(x, 10)`) and replaces them with
|
|
36
|
+
* `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` (ts-data-forge).
|
|
37
|
+
*
|
|
38
|
+
* Other radixes (e.g. `parseInt(x, 16)`) are intentionally left untouched, as
|
|
39
|
+
* `Num.safeParseInt` only supports base 10.
|
|
40
|
+
*/
|
|
41
|
+
export const preferNumSafeParseInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
42
|
+
meta: {
|
|
43
|
+
type: 'suggestion',
|
|
44
|
+
docs: {
|
|
45
|
+
description:
|
|
46
|
+
'Replace `parseInt(x, 10)` with `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` from ts-data-forge.',
|
|
47
|
+
},
|
|
48
|
+
fixable: 'code',
|
|
49
|
+
schema: [],
|
|
50
|
+
messages: {
|
|
51
|
+
useSafeParseInt:
|
|
52
|
+
'Replace `{{original}}` with `Result.unwrapOkOr(Num.safeParseInt({{argName}}), Number.NaN)` from ts-data-forge.',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
create: (context) => {
|
|
57
|
+
const sourceCode = context.sourceCode;
|
|
58
|
+
|
|
59
|
+
const program = sourceCode.ast;
|
|
60
|
+
|
|
61
|
+
const tsDataForgeImport = getTsDataForgeImport(program);
|
|
62
|
+
|
|
63
|
+
const services = context.sourceCode.parserServices;
|
|
64
|
+
|
|
65
|
+
const mut_nodesToFix: {
|
|
66
|
+
node: TSESTree.CallExpression;
|
|
67
|
+
argExpression: TSESTree.Expression;
|
|
68
|
+
}[] = [];
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
CallExpression: (node) => {
|
|
72
|
+
const { callee } = node;
|
|
73
|
+
|
|
74
|
+
// Match `parseInt(...)` or `Number.parseInt(...)`.
|
|
75
|
+
const isGlobalParseInt =
|
|
76
|
+
callee.type === AST_NODE_TYPES.Identifier &&
|
|
77
|
+
callee.name === 'parseInt';
|
|
78
|
+
|
|
79
|
+
const isNumberParseInt =
|
|
80
|
+
callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
81
|
+
!callee.computed &&
|
|
82
|
+
callee.object.type === AST_NODE_TYPES.Identifier &&
|
|
83
|
+
callee.object.name === 'Number' &&
|
|
84
|
+
callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
85
|
+
callee.property.name === 'parseInt';
|
|
86
|
+
|
|
87
|
+
if (!isGlobalParseInt && !isNumberParseInt) return;
|
|
88
|
+
|
|
89
|
+
const args = node.arguments;
|
|
90
|
+
|
|
91
|
+
const firstArg = args[0];
|
|
92
|
+
|
|
93
|
+
if (firstArg === undefined) return;
|
|
94
|
+
|
|
95
|
+
// Spread argument (`parseInt(...rest)`) cannot be rewritten safely.
|
|
96
|
+
if (firstArg.type === AST_NODE_TYPES.SpreadElement) return;
|
|
97
|
+
|
|
98
|
+
// Only base 10: accept a missing radix or an explicit literal `10`.
|
|
99
|
+
if (args.length >= 2) {
|
|
100
|
+
const radix = args[1];
|
|
101
|
+
|
|
102
|
+
if (radix?.type !== AST_NODE_TYPES.Literal || radix.value !== 10) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The argument must be a `string` so the autofix is type-safe against
|
|
108
|
+
// `Num.safeParseInt(s: string)`. Without type information, skip.
|
|
109
|
+
if (services?.program == null) return;
|
|
110
|
+
|
|
111
|
+
const checker = services.program.getTypeChecker();
|
|
112
|
+
|
|
113
|
+
const tsNode = services.esTreeNodeToTSNodeMap?.get(firstArg);
|
|
114
|
+
|
|
115
|
+
if (tsNode === undefined) return;
|
|
116
|
+
|
|
117
|
+
const argType = checker.getTypeAtLocation(tsNode);
|
|
118
|
+
|
|
119
|
+
if (!isStringType(argType)) return;
|
|
120
|
+
|
|
121
|
+
mut_nodesToFix.push({ node, argExpression: firstArg });
|
|
122
|
+
},
|
|
123
|
+
'Program:exit': () => {
|
|
124
|
+
const namedImports = getNamedImports(tsDataForgeImport);
|
|
125
|
+
|
|
126
|
+
const missingImports = (['Num', 'Result'] as const).filter(
|
|
127
|
+
(name) => !namedImports.includes(name),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
for (const [
|
|
131
|
+
index,
|
|
132
|
+
{ node, argExpression },
|
|
133
|
+
] of mut_nodesToFix.entries()) {
|
|
134
|
+
const argText = sourceCode.getText(argExpression);
|
|
135
|
+
|
|
136
|
+
const originalText = sourceCode.getText(node);
|
|
137
|
+
|
|
138
|
+
context.report({
|
|
139
|
+
node,
|
|
140
|
+
messageId: 'useSafeParseInt',
|
|
141
|
+
data: {
|
|
142
|
+
original: originalText,
|
|
143
|
+
argName: argText,
|
|
144
|
+
},
|
|
145
|
+
fix: (fixer) => {
|
|
146
|
+
const core = `Result.unwrapOkOr(Num.safeParseInt(${argText}), Number.NaN)`;
|
|
147
|
+
|
|
148
|
+
const importFixes =
|
|
149
|
+
index === 0 && missingImports.length > 0
|
|
150
|
+
? buildImportFixes(
|
|
151
|
+
fixer,
|
|
152
|
+
program,
|
|
153
|
+
tsDataForgeImport,
|
|
154
|
+
missingImports,
|
|
155
|
+
)
|
|
156
|
+
: [];
|
|
157
|
+
|
|
158
|
+
return [...importFixes, fixer.replaceText(node, core)];
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
defaultOptions: [],
|
|
166
|
+
} as const;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import dedent from 'dedent';
|
|
4
|
+
import { preferNumSafeParseInt } from './prefer-num-safe-parse-int.mjs';
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2020,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
projectService: {
|
|
13
|
+
allowDefaultProject: ['*.ts*'],
|
|
14
|
+
},
|
|
15
|
+
tsconfigRootDir: `${import.meta.dirname}/../..`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('prefer-num-safe-parse-int', () => {
|
|
21
|
+
tester.run('prefer-num-safe-parse-int', preferNumSafeParseInt, {
|
|
22
|
+
valid: [
|
|
23
|
+
{
|
|
24
|
+
name: 'ignores non-base-10 radix',
|
|
25
|
+
code: dedent`
|
|
26
|
+
const s = "ff";
|
|
27
|
+
const n = parseInt(s, 16);
|
|
28
|
+
`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'ignores number arguments (autofix would be unsafe)',
|
|
32
|
+
code: dedent`
|
|
33
|
+
const x = 42;
|
|
34
|
+
const n = parseInt(x, 10);
|
|
35
|
+
`,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'ignores never-typed arguments',
|
|
39
|
+
code: dedent`
|
|
40
|
+
declare const x: string & number;
|
|
41
|
+
const n = parseInt(x, 10);
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'ignores unrelated calls',
|
|
46
|
+
code: dedent`
|
|
47
|
+
const s = "1";
|
|
48
|
+
const n = Number(s);
|
|
49
|
+
`,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
invalid: [
|
|
53
|
+
{
|
|
54
|
+
name: 'replaces parseInt(s, 10) and imports Num + Result',
|
|
55
|
+
code: dedent`
|
|
56
|
+
const s = "123";
|
|
57
|
+
const n = parseInt(s, 10);
|
|
58
|
+
`,
|
|
59
|
+
output: dedent`
|
|
60
|
+
import { Num, Result } from 'ts-data-forge';
|
|
61
|
+
const s = "123";
|
|
62
|
+
const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
63
|
+
`,
|
|
64
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'replaces parseInt(s) without radix',
|
|
68
|
+
code: dedent`
|
|
69
|
+
const s = "123";
|
|
70
|
+
const n = parseInt(s);
|
|
71
|
+
`,
|
|
72
|
+
output: dedent`
|
|
73
|
+
import { Num, Result } from 'ts-data-forge';
|
|
74
|
+
const s = "123";
|
|
75
|
+
const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
76
|
+
`,
|
|
77
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'replaces Number.parseInt(s, 10)',
|
|
81
|
+
code: dedent`
|
|
82
|
+
const s = "123";
|
|
83
|
+
const n = Number.parseInt(s, 10);
|
|
84
|
+
`,
|
|
85
|
+
output: dedent`
|
|
86
|
+
import { Num, Result } from 'ts-data-forge';
|
|
87
|
+
const s = "123";
|
|
88
|
+
const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
89
|
+
`,
|
|
90
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'adds only the missing Result import when Num is present',
|
|
94
|
+
code: dedent`
|
|
95
|
+
import { Num } from 'ts-data-forge';
|
|
96
|
+
|
|
97
|
+
const s = "123";
|
|
98
|
+
const n = parseInt(s, 10);
|
|
99
|
+
`,
|
|
100
|
+
output: dedent`
|
|
101
|
+
import { Result } from 'ts-data-forge';
|
|
102
|
+
import { Num } from 'ts-data-forge';
|
|
103
|
+
|
|
104
|
+
const s = "123";
|
|
105
|
+
const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
106
|
+
`,
|
|
107
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: 'wraps in parentheses in an operator context',
|
|
111
|
+
code: dedent`
|
|
112
|
+
const s = "123";
|
|
113
|
+
const ok = parseInt(s, 10) > 5;
|
|
114
|
+
`,
|
|
115
|
+
output: dedent`
|
|
116
|
+
import { Num, Result } from 'ts-data-forge';
|
|
117
|
+
const s = "123";
|
|
118
|
+
const ok = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN) > 5;
|
|
119
|
+
`,
|
|
120
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'preserves a complex string argument expression',
|
|
124
|
+
code: dedent`
|
|
125
|
+
const get = (k: string): string => k;
|
|
126
|
+
const n = parseInt(get("x").trim(), 10);
|
|
127
|
+
`,
|
|
128
|
+
output: dedent`
|
|
129
|
+
import { Num, Result } from 'ts-data-forge';
|
|
130
|
+
const get = (k: string): string => k;
|
|
131
|
+
const n = Result.unwrapOkOr(Num.safeParseInt(get("x").trim()), Number.NaN);
|
|
132
|
+
`,
|
|
133
|
+
errors: [{ messageId: 'useSafeParseInt' }],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
}, 20000);
|
|
@@ -9,6 +9,8 @@ import { preferAsInt } from './prefer-as-int.mjs';
|
|
|
9
9
|
import { preferComparisonOverNullishGuard } from './prefer-comparison-over-nullish-guard.mjs';
|
|
10
10
|
import { preferIsNonNullObject } from './prefer-is-non-null-object.mjs';
|
|
11
11
|
import { preferIsRecordAndHasKey } from './prefer-is-record-and-has-key.mjs';
|
|
12
|
+
import { preferNumSafeParseFloat } from './prefer-num-safe-parse-float.mjs';
|
|
13
|
+
import { preferNumSafeParseInt } from './prefer-num-safe-parse-int.mjs';
|
|
12
14
|
import { preferRangeForLoop } from './prefer-range-for-loop.mjs';
|
|
13
15
|
|
|
14
16
|
export const tsDataForgeRules = {
|
|
@@ -21,6 +23,8 @@ export const tsDataForgeRules = {
|
|
|
21
23
|
'prefer-is-non-null-object': preferIsNonNullObject,
|
|
22
24
|
'prefer-range-for-loop': preferRangeForLoop,
|
|
23
25
|
'prefer-is-record-and-has-key': preferIsRecordAndHasKey,
|
|
26
|
+
'prefer-num-safe-parse-int': preferNumSafeParseInt,
|
|
27
|
+
'prefer-num-safe-parse-float': preferNumSafeParseFloat,
|
|
24
28
|
'no-unnecessary-type-guard': noUnnecessaryTypeGuard,
|
|
25
29
|
'prefer-comparison-over-nullish-guard': preferComparisonOverNullishGuard,
|
|
26
30
|
} as const satisfies ESLintPlugin['rules'];
|
|
@@ -13,6 +13,8 @@ export const eslintTsDataForgeRules = {
|
|
|
13
13
|
'ts-data-forge/prefer-arr-is-array-at-least-length': 'error',
|
|
14
14
|
'ts-data-forge/prefer-arr-is-array-of-length': 'error',
|
|
15
15
|
'ts-data-forge/prefer-is-record-and-has-key': 'error',
|
|
16
|
+
'ts-data-forge/prefer-num-safe-parse-int': 'error',
|
|
17
|
+
'ts-data-forge/prefer-num-safe-parse-float': 'error',
|
|
16
18
|
'ts-data-forge/no-unnecessary-type-guard': withDefaultOption('error'),
|
|
17
19
|
'ts-data-forge/prefer-comparison-over-nullish-guard': 'error',
|
|
18
20
|
} as const satisfies EslintTsDataForgeRules;
|
|
@@ -306,7 +306,13 @@ export const eslintUnicornRules = {
|
|
|
306
306
|
// This rule is disabled because it would require the container to be directly included in the React hooks dependencies.
|
|
307
307
|
'unicorn/prefer-minimal-ternary': 'off',
|
|
308
308
|
|
|
309
|
-
|
|
309
|
+
// Disabled in favor of `ts-data-forge/prefer-num-safe-parse-int`, which
|
|
310
|
+
// rewrites `parseInt(x, 10)` to `Num.safeParseInt(x)` instead of
|
|
311
|
+
// `Math.trunc(Number(x))`. The latter is hard to read and silently changes
|
|
312
|
+
// parsing semantics (e.g. `Number('')` is `0` whereas `parseInt('', 10)` is
|
|
313
|
+
// `NaN`).
|
|
314
|
+
'unicorn/prefer-number-coercion': 'off',
|
|
315
|
+
|
|
310
316
|
'unicorn/prefer-number-is-safe-integer': 'error',
|
|
311
317
|
'unicorn/prefer-object-define-properties': 'error',
|
|
312
318
|
'unicorn/prefer-object-destructuring-defaults': 'error',
|
|
@@ -142,6 +142,36 @@ namespace PreferIsRecordAndHasKey {
|
|
|
142
142
|
export type RuleEntry = Linter.StringSeverity;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* @description Replace `parseInt(x, 10)` with `Result.unwrapOkOr(Num.safeParseInt(x), Number.NaN)` from ts-data-forge.
|
|
147
|
+
*
|
|
148
|
+
* ```md
|
|
149
|
+
* | key | value |
|
|
150
|
+
* | :--------- | :--------- |
|
|
151
|
+
* | type | suggestion |
|
|
152
|
+
* | deprecated | false |
|
|
153
|
+
* | fixable | code |
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
namespace PreferNumSafeParseInt {
|
|
157
|
+
export type RuleEntry = Linter.StringSeverity;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @description Replace `parseFloat(x)`, `Number.parseFloat(x)`, or `Number(x)` (when x is a string) with `Result.unwrapOkOr(Num.safeParseFloat(x), Number.NaN)` from ts-data-forge.
|
|
162
|
+
*
|
|
163
|
+
* ```md
|
|
164
|
+
* | key | value |
|
|
165
|
+
* | :--------- | :--------- |
|
|
166
|
+
* | type | suggestion |
|
|
167
|
+
* | deprecated | false |
|
|
168
|
+
* | fixable | code |
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
namespace PreferNumSafeParseFloat {
|
|
172
|
+
export type RuleEntry = Linter.StringSeverity;
|
|
173
|
+
}
|
|
174
|
+
|
|
145
175
|
/**
|
|
146
176
|
* @description Detect ts-data-forge type guard calls that perform no narrowing (the argument type already satisfies, or can never satisfy, the guard).
|
|
147
177
|
*
|
|
@@ -213,6 +243,8 @@ export type EslintTsDataForgeRules = Readonly<{
|
|
|
213
243
|
'ts-data-forge/prefer-is-non-null-object': PreferIsNonNullObject.RuleEntry;
|
|
214
244
|
'ts-data-forge/prefer-range-for-loop': PreferRangeForLoop.RuleEntry;
|
|
215
245
|
'ts-data-forge/prefer-is-record-and-has-key': PreferIsRecordAndHasKey.RuleEntry;
|
|
246
|
+
'ts-data-forge/prefer-num-safe-parse-int': PreferNumSafeParseInt.RuleEntry;
|
|
247
|
+
'ts-data-forge/prefer-num-safe-parse-float': PreferNumSafeParseFloat.RuleEntry;
|
|
216
248
|
'ts-data-forge/no-unnecessary-type-guard': NoUnnecessaryTypeGuard.RuleEntry;
|
|
217
249
|
'ts-data-forge/prefer-comparison-over-nullish-guard': PreferComparisonOverNullishGuard.RuleEntry;
|
|
218
250
|
}>;
|