eslint-plugin-ts-data-forge 0.10.3 → 0.10.5
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/rules/mutable-result.mjs.map +1 -1
- package/dist/rules/no-unnecessary-type-guard.mjs +1 -1
- package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
- package/dist/rules/prefer-arr-generate.mjs +1 -1
- package/dist/rules/prefer-arr-generate.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs +1 -1
- package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs +1 -1
- package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.mjs +1 -1
- package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.mjs +1 -1
- package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
- package/dist/rules/prefer-arr-is-non-empty.mjs +1 -1
- package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
- package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
- package/dist/rules/prefer-arr-scan.mjs +5 -2
- package/dist/rules/prefer-arr-scan.mjs.map +1 -1
- package/dist/rules/prefer-arr-sum.mjs +1 -1
- package/dist/rules/prefer-arr-sum.mjs.map +1 -1
- package/dist/rules/prefer-arr-uniq.mjs +1 -1
- package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
- package/dist/rules/prefer-as-int.mjs +1 -1
- package/dist/rules/prefer-as-int.mjs.map +1 -1
- package/dist/rules/prefer-canonical-array-slicing.mjs +1 -1
- package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-cast.mjs +1 -1
- package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
- package/dist/rules/prefer-canonical-length-guard.mjs +1 -1
- package/dist/rules/prefer-canonical-length-guard.mjs.map +1 -1
- package/dist/rules/prefer-comparison-over-nullish-guard.mjs +1 -1
- package/dist/rules/prefer-comparison-over-nullish-guard.mjs.map +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs +1 -1
- package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.mjs +1 -1
- package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -1
- package/dist/rules/prefer-range-for-loop.mjs +1 -1
- package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
- package/package.json +9 -9
- package/src/rules/mutable-result.mts +1 -1
- package/src/rules/no-unnecessary-type-guard.mts +1 -1
- package/src/rules/prefer-arr-generate.mts +1 -1
- package/src/rules/prefer-arr-is-array.test.mts +87 -5
- package/src/rules/prefer-arr-is-bounded-length-array.mts +1 -1
- package/src/rules/prefer-arr-is-fixed-length-array.mts +1 -1
- package/src/rules/prefer-arr-is-max-length-array.mts +1 -1
- package/src/rules/prefer-arr-is-min-length-array.mts +1 -1
- package/src/rules/prefer-arr-is-non-empty.mts +1 -1
- package/src/rules/prefer-arr-scan.mts +5 -2
- package/src/rules/prefer-arr-sum.mts +1 -1
- package/src/rules/prefer-arr-uniq.mts +1 -1
- package/src/rules/prefer-as-int.mts +1 -1
- package/src/rules/prefer-canonical-array-slicing.mts +2 -2
- package/src/rules/prefer-canonical-length-cast.mts +1 -1
- package/src/rules/prefer-canonical-length-guard.mts +1 -1
- package/src/rules/prefer-comparison-over-nullish-guard.mts +3 -3
- package/src/rules/prefer-is-non-null-object.test.mts +62 -37
- package/src/rules/prefer-is-record-and-has-key.test.mts +32 -17
- package/src/rules/prefer-num-safe-parse-float.test.mts +45 -21
- package/src/rules/prefer-num-safe-parse-int.test.mts +29 -14
- package/src/rules/prefer-obj-over-entries-round-trip.mts +1 -1
- package/src/rules/prefer-pipe-map-nullable.mts +2 -2
- package/src/rules/prefer-range-for-loop.mts +1 -1
|
@@ -32,6 +32,7 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
32
32
|
useIsBoundedLengthArray:
|
|
33
33
|
'Replace `{{original}}` with `Arr.isBoundedLengthArray({{arrayName}}, {{min}}, {{max}})` from ts-data-forge.',
|
|
34
34
|
},
|
|
35
|
+
defaultOptions: [],
|
|
35
36
|
},
|
|
36
37
|
|
|
37
38
|
create: (context) => {
|
|
@@ -141,5 +142,4 @@ export const preferArrIsBoundedLengthArray: TSESLint.RuleModule<
|
|
|
141
142
|
},
|
|
142
143
|
};
|
|
143
144
|
},
|
|
144
|
-
defaultOptions: [],
|
|
145
145
|
} as const;
|
|
@@ -33,6 +33,7 @@ export const preferArrIsFixedLengthArray: TSESLint.RuleModule<
|
|
|
33
33
|
useIsFixedLengthArray:
|
|
34
34
|
'Replace `{{original}}` with `Arr.isFixedLengthArray({{arrayName}}, {{length}})` from ts-data-forge.',
|
|
35
35
|
},
|
|
36
|
+
defaultOptions: [],
|
|
36
37
|
},
|
|
37
38
|
|
|
38
39
|
create: (context) => {
|
|
@@ -139,5 +140,4 @@ export const preferArrIsFixedLengthArray: TSESLint.RuleModule<
|
|
|
139
140
|
},
|
|
140
141
|
};
|
|
141
142
|
},
|
|
142
|
-
defaultOptions: [],
|
|
143
143
|
} as const;
|
|
@@ -34,6 +34,7 @@ export const preferArrIsMaxLengthArray: TSESLint.RuleModule<
|
|
|
34
34
|
useIsMaxLengthArray:
|
|
35
35
|
'Replace `{{original}}` with `Arr.isMaxLengthArray({{arrayName}}, {{length}})` from ts-data-forge.',
|
|
36
36
|
},
|
|
37
|
+
defaultOptions: [],
|
|
37
38
|
},
|
|
38
39
|
|
|
39
40
|
create: (context) => {
|
|
@@ -142,5 +143,4 @@ export const preferArrIsMaxLengthArray: TSESLint.RuleModule<
|
|
|
142
143
|
},
|
|
143
144
|
};
|
|
144
145
|
},
|
|
145
|
-
defaultOptions: [],
|
|
146
146
|
} as const;
|
|
@@ -34,6 +34,7 @@ export const preferArrIsMinLengthArray: TSESLint.RuleModule<
|
|
|
34
34
|
useIsMinLengthArray:
|
|
35
35
|
'Replace `{{original}}` with `Arr.isMinLengthArray({{arrayName}}, {{length}})` from ts-data-forge.',
|
|
36
36
|
},
|
|
37
|
+
defaultOptions: [],
|
|
37
38
|
},
|
|
38
39
|
|
|
39
40
|
create: (context) => {
|
|
@@ -142,5 +143,4 @@ export const preferArrIsMinLengthArray: TSESLint.RuleModule<
|
|
|
142
143
|
},
|
|
143
144
|
};
|
|
144
145
|
},
|
|
145
|
-
defaultOptions: [],
|
|
146
146
|
} as const;
|
|
@@ -30,6 +30,7 @@ export const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
30
30
|
useIsNonEmpty:
|
|
31
31
|
'Replace `{{original}}` with `Arr.isNonEmpty({{arrayName}})` from ts-data-forge.',
|
|
32
32
|
},
|
|
33
|
+
defaultOptions: [],
|
|
33
34
|
},
|
|
34
35
|
|
|
35
36
|
create: (context) => {
|
|
@@ -125,5 +126,4 @@ export const preferArrIsNonEmpty: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
125
126
|
},
|
|
126
127
|
};
|
|
127
128
|
},
|
|
128
|
-
defaultOptions: [],
|
|
129
129
|
} as const;
|
|
@@ -21,7 +21,10 @@ type Options = readonly [];
|
|
|
21
21
|
type MessageIds = 'preferArrScanPrefix' | 'preferArrScanAccumulate';
|
|
22
22
|
|
|
23
23
|
/** Array methods that cut a prefix or a suffix out of the array they are called on. */
|
|
24
|
-
const SLICING_METHODS: ReadonlySet<string> = new Set([
|
|
24
|
+
const SLICING_METHODS: ReadonlySet<string> = new Set<string>([
|
|
25
|
+
'slice',
|
|
26
|
+
'subarray',
|
|
27
|
+
]);
|
|
25
28
|
|
|
26
29
|
/** A `map` call whose callback ignores the element it is handed. */
|
|
27
30
|
type PrefixCandidate = Readonly<{
|
|
@@ -171,6 +174,7 @@ export const preferArrScan: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
171
174
|
preferArrScanAccumulate:
|
|
172
175
|
'Rebuilding the accumulator array on every step copies it each time. `Arr.scan` from ts-data-forge accumulates in one pass and returns the initial value followed by every intermediate one.',
|
|
173
176
|
},
|
|
177
|
+
defaultOptions: [],
|
|
174
178
|
},
|
|
175
179
|
|
|
176
180
|
create: (context) => {
|
|
@@ -553,7 +557,6 @@ export const preferArrScan: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
553
557
|
},
|
|
554
558
|
};
|
|
555
559
|
},
|
|
556
|
-
defaultOptions: [],
|
|
557
560
|
} as const;
|
|
558
561
|
|
|
559
562
|
/**
|
|
@@ -33,6 +33,7 @@ export const preferArrSum: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
33
33
|
useArrSumBy:
|
|
34
34
|
'Replace with `Arr.sumBy({{arrayName}}, {{mapper}})` from ts-data-forge.',
|
|
35
35
|
},
|
|
36
|
+
defaultOptions: [],
|
|
36
37
|
},
|
|
37
38
|
|
|
38
39
|
create: (context) => {
|
|
@@ -306,5 +307,4 @@ export const preferArrSum: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
306
307
|
},
|
|
307
308
|
};
|
|
308
309
|
},
|
|
309
|
-
defaultOptions: [],
|
|
310
310
|
} as const;
|
|
@@ -45,6 +45,7 @@ export const preferArrUniq: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
45
45
|
suggestArrUniq:
|
|
46
46
|
'Replace with `Arr.uniq({{arrayName}})` from ts-data-forge (the result becomes a readonly array).',
|
|
47
47
|
},
|
|
48
|
+
defaultOptions: [],
|
|
48
49
|
},
|
|
49
50
|
|
|
50
51
|
create: (context) => {
|
|
@@ -213,7 +214,6 @@ export const preferArrUniq: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
213
214
|
},
|
|
214
215
|
};
|
|
215
216
|
},
|
|
216
|
-
defaultOptions: [],
|
|
217
217
|
} as const;
|
|
218
218
|
|
|
219
219
|
/**
|
|
@@ -30,6 +30,7 @@ export const preferAsInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
30
30
|
useBrandedNumberCastFunction:
|
|
31
31
|
'Replace `as {{typeName}}` with `{{functionName}}()` from ts-data-forge.',
|
|
32
32
|
},
|
|
33
|
+
defaultOptions: [],
|
|
33
34
|
},
|
|
34
35
|
|
|
35
36
|
create: (context) => {
|
|
@@ -112,7 +113,6 @@ export const preferAsInt: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
112
113
|
},
|
|
113
114
|
};
|
|
114
115
|
},
|
|
115
|
-
defaultOptions: [],
|
|
116
116
|
} as const;
|
|
117
117
|
|
|
118
118
|
const getBrandedNumberTypeInfo = (
|
|
@@ -113,7 +113,7 @@ const rootIdentifierName = (wrapped: TSESTree.Node): string | undefined => {
|
|
|
113
113
|
|
|
114
114
|
type ComparisonOperator = '!==' | '<' | '<=' | '>' | '>=';
|
|
115
115
|
|
|
116
|
-
const COMPARISON_OPERATORS: ReadonlySet<string> = new Set([
|
|
116
|
+
const COMPARISON_OPERATORS: ReadonlySet<string> = new Set<string>([
|
|
117
117
|
'!==',
|
|
118
118
|
'<',
|
|
119
119
|
'<=',
|
|
@@ -192,6 +192,7 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
|
|
|
192
192
|
preferCanonicalArraySlicing:
|
|
193
193
|
'Replace with `{{replacement}}` from ts-data-forge.',
|
|
194
194
|
},
|
|
195
|
+
defaultOptions: [],
|
|
195
196
|
},
|
|
196
197
|
|
|
197
198
|
create: (context) => {
|
|
@@ -877,5 +878,4 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
|
|
|
877
878
|
},
|
|
878
879
|
};
|
|
879
880
|
},
|
|
880
|
-
defaultOptions: [],
|
|
881
881
|
} as const;
|
|
@@ -141,6 +141,7 @@ export const preferCanonicalLengthCast: TSESLint.RuleModule<
|
|
|
141
141
|
useCanonicalCast:
|
|
142
142
|
'Use `{{arrName}}.{{replacement}}(...)` instead of `{{arrName}}.{{cast}}({{boundsText}})`: with these bounds the result type is the same (or stricter), and `{{replacement}}` names the constraint directly.',
|
|
143
143
|
},
|
|
144
|
+
defaultOptions: [],
|
|
144
145
|
},
|
|
145
146
|
|
|
146
147
|
create: (context) => {
|
|
@@ -197,7 +198,6 @@ export const preferCanonicalLengthCast: TSESLint.RuleModule<
|
|
|
197
198
|
},
|
|
198
199
|
};
|
|
199
200
|
},
|
|
200
|
-
defaultOptions: [],
|
|
201
201
|
} as const;
|
|
202
202
|
|
|
203
203
|
/** The `Arr.<cast>` method name of `node`, or `undefined` for other calls. */
|
|
@@ -116,6 +116,7 @@ export const preferCanonicalLengthGuard: TSESLint.RuleModule<
|
|
|
116
116
|
fixable: 'code',
|
|
117
117
|
schema: [],
|
|
118
118
|
messages: MESSAGES,
|
|
119
|
+
defaultOptions: [],
|
|
119
120
|
},
|
|
120
121
|
|
|
121
122
|
create: (context) => {
|
|
@@ -180,7 +181,6 @@ export const preferCanonicalLengthGuard: TSESLint.RuleModule<
|
|
|
180
181
|
},
|
|
181
182
|
]);
|
|
182
183
|
},
|
|
183
|
-
defaultOptions: [],
|
|
184
184
|
} as const;
|
|
185
185
|
|
|
186
186
|
/**
|
|
@@ -36,7 +36,7 @@ const COMPARISON_GUARDS: ReadonlyRecord<string, ComparisonSpec> = {
|
|
|
36
36
|
* intended, but are parenthesized so that the type or the grouping is not read
|
|
37
37
|
* as part of the comparison.
|
|
38
38
|
*/
|
|
39
|
-
const ARG_NEEDS_PARENS: ReadonlySet<string> = new Set([
|
|
39
|
+
const ARG_NEEDS_PARENS: ReadonlySet<string> = new Set<string>([
|
|
40
40
|
AST_NODE_TYPES.LogicalExpression,
|
|
41
41
|
AST_NODE_TYPES.ConditionalExpression,
|
|
42
42
|
AST_NODE_TYPES.AssignmentExpression,
|
|
@@ -48,7 +48,7 @@ const ARG_NEEDS_PARENS: ReadonlySet<string> = new Set([
|
|
|
48
48
|
]);
|
|
49
49
|
|
|
50
50
|
/** Binary operators that bind no tighter than `===` / `!==`. */
|
|
51
|
-
const LOOSE_BINARY_OPERATORS: ReadonlySet<string> = new Set([
|
|
51
|
+
const LOOSE_BINARY_OPERATORS: ReadonlySet<string> = new Set<string>([
|
|
52
52
|
'|',
|
|
53
53
|
'^',
|
|
54
54
|
'&',
|
|
@@ -116,6 +116,7 @@ export const preferComparisonOverNullishGuard: TSESLint.RuleModule<
|
|
|
116
116
|
preferComparison:
|
|
117
117
|
'Prefer `{{comparison}}` over calling `{{name}}` with an explicit argument.',
|
|
118
118
|
},
|
|
119
|
+
defaultOptions: [],
|
|
119
120
|
},
|
|
120
121
|
|
|
121
122
|
create: (context) => {
|
|
@@ -171,5 +172,4 @@ export const preferComparisonOverNullishGuard: TSESLint.RuleModule<
|
|
|
171
172
|
},
|
|
172
173
|
};
|
|
173
174
|
},
|
|
174
|
-
defaultOptions: [],
|
|
175
175
|
} as const;
|
|
@@ -60,24 +60,6 @@ describe('prefer-is-non-null-object', () => {
|
|
|
60
60
|
`,
|
|
61
61
|
errors: [{ messageId: 'useIsNonNullObject' }],
|
|
62
62
|
},
|
|
63
|
-
{
|
|
64
|
-
name: 'replaces multiple typeof object checks with isNonNullObject imports',
|
|
65
|
-
code: dedent`
|
|
66
|
-
const u = {};
|
|
67
|
-
const ok = typeof u === "object" && u !== null;
|
|
68
|
-
const ok2 = typeof u === "object" && u !== null;
|
|
69
|
-
`,
|
|
70
|
-
output: dedent`
|
|
71
|
-
import { isNonNullObject } from 'ts-data-forge';
|
|
72
|
-
const u = {};
|
|
73
|
-
const ok = isNonNullObject(u);
|
|
74
|
-
const ok2 = isNonNullObject(u);
|
|
75
|
-
`,
|
|
76
|
-
errors: [
|
|
77
|
-
{ messageId: 'useIsNonNullObject' },
|
|
78
|
-
{ messageId: 'useIsNonNullObject' },
|
|
79
|
-
],
|
|
80
|
-
},
|
|
81
63
|
] as const),
|
|
82
64
|
|
|
83
65
|
...([
|
|
@@ -124,8 +106,7 @@ describe('prefer-is-non-null-object', () => {
|
|
|
124
106
|
const ok = typeof u === "object" && u !== null;
|
|
125
107
|
`,
|
|
126
108
|
output: dedent`
|
|
127
|
-
import { isNonNullObject } from 'ts-data-forge';
|
|
128
|
-
import { asInt } from 'ts-data-forge';
|
|
109
|
+
import { asInt, isNonNullObject } from 'ts-data-forge';
|
|
129
110
|
|
|
130
111
|
const ok = isNonNullObject(u);
|
|
131
112
|
`,
|
|
@@ -141,9 +122,8 @@ describe('prefer-is-non-null-object', () => {
|
|
|
141
122
|
noop(typeof u === "object" && u !== null);
|
|
142
123
|
`,
|
|
143
124
|
output: dedent`
|
|
144
|
-
import { isNonNullObject } from 'ts-data-forge';
|
|
145
125
|
import { noop } from './noop.mjs';
|
|
146
|
-
import { asInt } from 'ts-data-forge';
|
|
126
|
+
import { asInt, isNonNullObject } from 'ts-data-forge';
|
|
147
127
|
|
|
148
128
|
const u = {};
|
|
149
129
|
noop(isNonNullObject(u));
|
|
@@ -151,6 +131,32 @@ describe('prefer-is-non-null-object', () => {
|
|
|
151
131
|
errors: [{ messageId: 'useIsNonNullObject' }],
|
|
152
132
|
},
|
|
153
133
|
] as const),
|
|
134
|
+
{
|
|
135
|
+
name: 'replaces multiple typeof object checks with isNonNullObject imports',
|
|
136
|
+
code: dedent`
|
|
137
|
+
const u = {};
|
|
138
|
+
const ok = typeof u === "object" && u !== null;
|
|
139
|
+
const ok2 = typeof u === "object" && u !== null;
|
|
140
|
+
`,
|
|
141
|
+
output: [
|
|
142
|
+
dedent`
|
|
143
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
144
|
+
const u = {};
|
|
145
|
+
const ok = isNonNullObject(u);
|
|
146
|
+
const ok2 = typeof u === "object" && u !== null;
|
|
147
|
+
`,
|
|
148
|
+
dedent`
|
|
149
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
150
|
+
const u = {};
|
|
151
|
+
const ok = isNonNullObject(u);
|
|
152
|
+
const ok2 = isNonNullObject(u);
|
|
153
|
+
`,
|
|
154
|
+
],
|
|
155
|
+
errors: [
|
|
156
|
+
{ messageId: 'useIsNonNullObject' },
|
|
157
|
+
{ messageId: 'useIsNonNullObject' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
154
160
|
],
|
|
155
161
|
});
|
|
156
162
|
}, 20000);
|
|
@@ -298,15 +304,26 @@ describe('prefer-is-non-null-object in other forms', () => {
|
|
|
298
304
|
const y = a && typeof u === 'object' && u !== null;
|
|
299
305
|
const z = a && u !== null && (typeof u === 'object') && b;
|
|
300
306
|
`,
|
|
301
|
-
output:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
307
|
+
output: [
|
|
308
|
+
dedent`
|
|
309
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
310
|
+
declare const u: unknown;
|
|
311
|
+
declare const a: boolean;
|
|
312
|
+
declare const b: boolean;
|
|
313
|
+
const x = isNonNullObject(u) && 'k' in u;
|
|
314
|
+
const y = a && typeof u === 'object' && u !== null;
|
|
315
|
+
const z = a && u !== null && (typeof u === 'object') && b;
|
|
316
|
+
`,
|
|
317
|
+
dedent`
|
|
318
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
319
|
+
declare const u: unknown;
|
|
320
|
+
declare const a: boolean;
|
|
321
|
+
declare const b: boolean;
|
|
322
|
+
const x = isNonNullObject(u) && 'k' in u;
|
|
323
|
+
const y = a && isNonNullObject(u);
|
|
324
|
+
const z = a && isNonNullObject(u) && b;
|
|
325
|
+
`,
|
|
326
|
+
],
|
|
310
327
|
errors: [
|
|
311
328
|
{ messageId: 'useIsNonNullObject' },
|
|
312
329
|
{ messageId: 'useIsNonNullObject' },
|
|
@@ -320,12 +337,20 @@ describe('prefer-is-non-null-object in other forms', () => {
|
|
|
320
337
|
declare const v: unknown;
|
|
321
338
|
const ok = typeof u === 'object' && u !== null && v !== null && typeof v === 'object';
|
|
322
339
|
`,
|
|
323
|
-
output:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
340
|
+
output: [
|
|
341
|
+
dedent`
|
|
342
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
343
|
+
declare const u: unknown;
|
|
344
|
+
declare const v: unknown;
|
|
345
|
+
const ok = isNonNullObject(u) && v !== null && typeof v === 'object';
|
|
346
|
+
`,
|
|
347
|
+
dedent`
|
|
348
|
+
import { isNonNullObject } from 'ts-data-forge';
|
|
349
|
+
declare const u: unknown;
|
|
350
|
+
declare const v: unknown;
|
|
351
|
+
const ok = isNonNullObject(u) && isNonNullObject(v);
|
|
352
|
+
`,
|
|
353
|
+
],
|
|
329
354
|
errors: [
|
|
330
355
|
{ messageId: 'useIsNonNullObject' },
|
|
331
356
|
{ messageId: 'useIsNonNullObject' },
|
|
@@ -85,13 +85,22 @@ describe('prefer-is-record-and-has-key', () => {
|
|
|
85
85
|
const a = Object.hasOwn(rec, 'a');
|
|
86
86
|
const b = Object.hasOwn(unk, 'b');
|
|
87
87
|
`,
|
|
88
|
-
output:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
output: [
|
|
89
|
+
dedent`
|
|
90
|
+
import { hasKey } from 'ts-data-forge';
|
|
91
|
+
declare const rec: Record<string, unknown>;
|
|
92
|
+
declare const unk: unknown;
|
|
93
|
+
const a = hasKey(rec, 'a');
|
|
94
|
+
const b = Object.hasOwn(unk, 'b');
|
|
95
|
+
`,
|
|
96
|
+
dedent`
|
|
97
|
+
import { hasKey, isRecord } from 'ts-data-forge';
|
|
98
|
+
declare const rec: Record<string, unknown>;
|
|
99
|
+
declare const unk: unknown;
|
|
100
|
+
const a = hasKey(rec, 'a');
|
|
101
|
+
const b = (isRecord(unk) && hasKey(unk, 'b'));
|
|
102
|
+
`,
|
|
103
|
+
],
|
|
95
104
|
errors: [
|
|
96
105
|
{ messageId: 'useHasKey' },
|
|
97
106
|
{ messageId: 'useIsRecordAndHasKey' },
|
|
@@ -162,8 +171,7 @@ describe('prefer-is-record-and-has-key', () => {
|
|
|
162
171
|
const ok = Object.hasOwn(obj, 'a');
|
|
163
172
|
`,
|
|
164
173
|
output: dedent`
|
|
165
|
-
import { hasKey } from 'ts-data-forge';
|
|
166
|
-
import { isRecord } from 'ts-data-forge';
|
|
174
|
+
import { isRecord, hasKey } from 'ts-data-forge';
|
|
167
175
|
|
|
168
176
|
const obj = { a: 1 };
|
|
169
177
|
const ok = (isRecord(obj) && hasKey(obj, 'a'));
|
|
@@ -179,8 +187,7 @@ describe('prefer-is-record-and-has-key', () => {
|
|
|
179
187
|
const ok = 'a' in obj;
|
|
180
188
|
`,
|
|
181
189
|
output: dedent`
|
|
182
|
-
import { isRecord } from 'ts-data-forge';
|
|
183
|
-
import { hasKey } from 'ts-data-forge';
|
|
190
|
+
import { hasKey, isRecord } from 'ts-data-forge';
|
|
184
191
|
|
|
185
192
|
const obj = { a: 1 };
|
|
186
193
|
const ok = (isRecord(obj) && hasKey(obj, 'a'));
|
|
@@ -210,12 +217,20 @@ describe('prefer-is-record-and-has-key', () => {
|
|
|
210
217
|
const ok1 = Object.hasOwn(obj, 'a');
|
|
211
218
|
const ok2 = 'b' in obj;
|
|
212
219
|
`,
|
|
213
|
-
output:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
output: [
|
|
221
|
+
dedent`
|
|
222
|
+
import { isRecord, hasKey } from 'ts-data-forge';
|
|
223
|
+
const obj = { a: 1 };
|
|
224
|
+
const ok1 = (isRecord(obj) && hasKey(obj, 'a'));
|
|
225
|
+
const ok2 = 'b' in obj;
|
|
226
|
+
`,
|
|
227
|
+
dedent`
|
|
228
|
+
import { isRecord, hasKey } from 'ts-data-forge';
|
|
229
|
+
const obj = { a: 1 };
|
|
230
|
+
const ok1 = (isRecord(obj) && hasKey(obj, 'a'));
|
|
231
|
+
const ok2 = (isRecord(obj) && hasKey(obj, 'b'));
|
|
232
|
+
`,
|
|
233
|
+
],
|
|
219
234
|
errors: [
|
|
220
235
|
{ messageId: 'useIsRecordAndHasKey' },
|
|
221
236
|
{ messageId: 'useIsRecordAndHasKey' },
|
|
@@ -105,8 +105,7 @@ describe('prefer-num-safe-parse-float', () => {
|
|
|
105
105
|
const n = parseFloat(s);
|
|
106
106
|
`,
|
|
107
107
|
output: dedent`
|
|
108
|
-
import { Result } from 'ts-data-forge';
|
|
109
|
-
import { Num } from 'ts-data-forge';
|
|
108
|
+
import { Num, Result } from 'ts-data-forge';
|
|
110
109
|
|
|
111
110
|
const s = "3.14";
|
|
112
111
|
const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
@@ -145,13 +144,22 @@ describe('prefer-num-safe-parse-float', () => {
|
|
|
145
144
|
const b = Number.parseFloat(s);
|
|
146
145
|
const c = Number(s);
|
|
147
146
|
`,
|
|
148
|
-
output:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
147
|
+
output: [
|
|
148
|
+
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 = Number.parseFloat(s);
|
|
153
|
+
const c = Number(s);
|
|
154
|
+
`,
|
|
155
|
+
dedent`
|
|
156
|
+
import { Num, Result } from 'ts-data-forge';
|
|
157
|
+
const s = "1.5";
|
|
158
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
159
|
+
const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
160
|
+
const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
161
|
+
`,
|
|
162
|
+
],
|
|
155
163
|
errors: [
|
|
156
164
|
{ messageId: 'useSafeParseFloat' },
|
|
157
165
|
{ messageId: 'useSafeParseFloat' },
|
|
@@ -203,12 +211,20 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
|
|
|
203
211
|
const a = Number(s!);
|
|
204
212
|
const b = parseFloat(s satisfies string);
|
|
205
213
|
`,
|
|
206
|
-
output:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
output: [
|
|
215
|
+
dedent`
|
|
216
|
+
import { Num, Result } from 'ts-data-forge';
|
|
217
|
+
declare const s: string;
|
|
218
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
|
|
219
|
+
const b = parseFloat(s satisfies string);
|
|
220
|
+
`,
|
|
221
|
+
dedent`
|
|
222
|
+
import { Num, Result } from 'ts-data-forge';
|
|
223
|
+
declare const s: string;
|
|
224
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
|
|
225
|
+
const b = Result.unwrapOkOr(Num.safeParseFloat(s satisfies string), Number.NaN);
|
|
226
|
+
`,
|
|
227
|
+
],
|
|
212
228
|
errors: [
|
|
213
229
|
{ messageId: 'useSafeParseFloat' },
|
|
214
230
|
{ messageId: 'useSafeParseFloat' },
|
|
@@ -221,12 +237,20 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
|
|
|
221
237
|
const a = (Number as NumberConstructor)(s);
|
|
222
238
|
const b = Number!.parseFloat(s);
|
|
223
239
|
`,
|
|
224
|
-
output:
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
240
|
+
output: [
|
|
241
|
+
dedent`
|
|
242
|
+
import { Num, Result } from 'ts-data-forge';
|
|
243
|
+
declare const s: string;
|
|
244
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
245
|
+
const b = Number!.parseFloat(s);
|
|
246
|
+
`,
|
|
247
|
+
dedent`
|
|
248
|
+
import { Num, Result } from 'ts-data-forge';
|
|
249
|
+
declare const s: string;
|
|
250
|
+
const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
251
|
+
const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
|
|
252
|
+
`,
|
|
253
|
+
],
|
|
230
254
|
errors: [
|
|
231
255
|
{ messageId: 'useSafeParseFloat' },
|
|
232
256
|
{ messageId: 'useSafeParseFloat' },
|
|
@@ -98,8 +98,7 @@ describe('prefer-num-safe-parse-int', () => {
|
|
|
98
98
|
const n = parseInt(s, 10);
|
|
99
99
|
`,
|
|
100
100
|
output: dedent`
|
|
101
|
-
import { Result } from 'ts-data-forge';
|
|
102
|
-
import { Num } from 'ts-data-forge';
|
|
101
|
+
import { Num, Result } from 'ts-data-forge';
|
|
103
102
|
|
|
104
103
|
const s = "123";
|
|
105
104
|
const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
@@ -162,12 +161,20 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
|
|
|
162
161
|
const a = parseInt(s, 10 as const);
|
|
163
162
|
const b = Number.parseInt(s!, 10 satisfies number);
|
|
164
163
|
`,
|
|
165
|
-
output:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
output: [
|
|
165
|
+
dedent`
|
|
166
|
+
import { Num, Result } from 'ts-data-forge';
|
|
167
|
+
declare const s: string;
|
|
168
|
+
const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
169
|
+
const b = Number.parseInt(s!, 10 satisfies number);
|
|
170
|
+
`,
|
|
171
|
+
dedent`
|
|
172
|
+
import { Num, Result } from 'ts-data-forge';
|
|
173
|
+
declare const s: string;
|
|
174
|
+
const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
175
|
+
const b = Result.unwrapOkOr(Num.safeParseInt(s!), Number.NaN);
|
|
176
|
+
`,
|
|
177
|
+
],
|
|
171
178
|
errors: [
|
|
172
179
|
{ messageId: 'useSafeParseInt' },
|
|
173
180
|
{ messageId: 'useSafeParseInt' },
|
|
@@ -180,12 +187,20 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
|
|
|
180
187
|
const a = (parseInt as typeof parseInt)(s);
|
|
181
188
|
const b = (Number as NumberConstructor)!.parseInt(s, 10);
|
|
182
189
|
`,
|
|
183
|
-
output:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
output: [
|
|
191
|
+
dedent`
|
|
192
|
+
import { Num, Result } from 'ts-data-forge';
|
|
193
|
+
declare const s: string;
|
|
194
|
+
const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
195
|
+
const b = (Number as NumberConstructor)!.parseInt(s, 10);
|
|
196
|
+
`,
|
|
197
|
+
dedent`
|
|
198
|
+
import { Num, Result } from 'ts-data-forge';
|
|
199
|
+
declare const s: string;
|
|
200
|
+
const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
201
|
+
const b = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
|
|
202
|
+
`,
|
|
203
|
+
],
|
|
189
204
|
errors: [
|
|
190
205
|
{ messageId: 'useSafeParseInt' },
|
|
191
206
|
{ messageId: 'useSafeParseInt' },
|
|
@@ -86,6 +86,7 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
86
86
|
useObjFilterMap:
|
|
87
87
|
'Replace this `Object.fromEntries(Object.entries(…).flatMap(…))` round trip with `Obj.filterMap` from ts-data-forge, which keeps the key types of the record in the result type.',
|
|
88
88
|
},
|
|
89
|
+
defaultOptions: [],
|
|
89
90
|
},
|
|
90
91
|
|
|
91
92
|
create: (context) => {
|
|
@@ -218,7 +219,6 @@ export const preferObjOverEntriesRoundTrip: TSESLint.RuleModule<
|
|
|
218
219
|
},
|
|
219
220
|
};
|
|
220
221
|
},
|
|
221
|
-
defaultOptions: [],
|
|
222
222
|
} as const;
|
|
223
223
|
|
|
224
224
|
/**
|
|
@@ -53,6 +53,7 @@ export const preferPipeMapNullable: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
53
53
|
suggestMapNullable:
|
|
54
54
|
'Replace `.map({{mapNullableName}}(…))` with `.mapNullable(…)` (the inferred type may be widened, or a comment or type assertion dropped).',
|
|
55
55
|
},
|
|
56
|
+
defaultOptions: [],
|
|
56
57
|
},
|
|
57
58
|
|
|
58
59
|
create: (context) => {
|
|
@@ -283,7 +284,6 @@ export const preferPipeMapNullable: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
283
284
|
},
|
|
284
285
|
};
|
|
285
286
|
},
|
|
286
|
-
defaultOptions: [],
|
|
287
287
|
} as const;
|
|
288
288
|
|
|
289
289
|
/**
|
|
@@ -294,7 +294,7 @@ export const preferPipeMapNullable: TSESLint.RuleModule<MessageIds, Options> = {
|
|
|
294
294
|
const PIPE_MODULES = [TS_DATA_FORGE_MODULE, 'ts-std-forge'] as const;
|
|
295
295
|
|
|
296
296
|
/** The methods of a `Pipe` that return another `Pipe`. */
|
|
297
|
-
const PIPE_CHAIN_METHODS: ReadonlySet<string> = new Set([
|
|
297
|
+
const PIPE_CHAIN_METHODS: ReadonlySet<string> = new Set<string>([
|
|
298
298
|
'map',
|
|
299
299
|
'mapNullable',
|
|
300
300
|
'mapOptional',
|